Reading Files from a Bundle

At this point you can create application bundles and add files and folders to the bundle. The last major task is to read the files from the bundle. This involves three steps.

  1. Get the application bundle.
  2. Find the file in the bundle.
  3. Open the file so you can read data from it.

I’m going to use the Core Foundation framework functions. If you’re writing a Cocoa application, look at Cocoa’s NSBundle class, which performs the same tasks as Core Foundation’s bundle functions.

Getting the Application Bundle

Call the function CFBundleGetMainBundle(), which returns the main bundle in the application.

CFBundleRef gameBundle = CFBundleGetMainBundle();

Finding a File in the Application Bundle

After getting the application’s main bundle, you must find the file in the bundle. Call the function CFBundleCopyResourceURL(), which returns the file’s location in the bundle. This function takes four arguments.

  • The bundle you retrieved by calling CFBundleGetMainBundle().
  • The file name.
  • The file extension.
  • A subdirectory in the bundle where the operating system should look for the file. Passing NULL tells the operating system to search the entire bundle. Unless you have a huge bundle with hundreds of files, passing NULL should be sufficient.
CFBundleRef gameBundle;
CFStringRef filename;
CFStringRef fileExtension;
CFStringRef subdirectory;
CFURLRef fileLocation;

fileLocation = CFBundleCopyResourceURL(gameBundle, filename, fileExtension, subdirectory);

Suppose you want to load a file named Background.png. There are two ways you can call CFBundleCopyResourceURL(). First, you can use Background as the file name and png as the extension. Second, you can use Background.png as the file name and NULL as the extension.

Opening the File

There are several ways to open files on Mac OS X. I’m going to focus on Apple’s technologies in Carbon to open files.

CFBundleCopyResourceURL() returns a variable of type CFURLRef, which you can use to open the file and read data from the file. The code to open the file depends on the type of file. For graphics and sound files, you would use QuickTime to open and read the file. I provide detailed instructions on using QuickTime in my QuickTime audio and texture loading articles.

To open data files you should call the function CFURLGetFSRef(). This function gives you a file system reference, a FSRef, that you pass to either a File Manager or Resource Manager function to open the file.

CFURLRef fileLocation;
FSRef fileToRead;
Boolean openedSuccessfully;

openedSuccessfully = CFURLGetFSRef(fileLocation, &fileToRead);

Call the File Manager function FSOpenFork() to open a data file.

OSErr error;
HFSUniStr255 forkName;
short refNum;

error = FSGetDataForkName(&forkName);

error = FSOpenFork(&fileToRead, forkName.length, forkName.unicode, fsRdPerm, &refNum);

Call the Resource Manager function FSOpenResFile() to open a resource file.

short refNum;
refNum = FSOpenResFile(&fileToRead, fsRdPerm);

Conclusion

Normally I include source code with my articles that provides the simplest possible example of the material I covered in the article. But it is hard to write an application that just loads a file from an application bundle. However, I have three code samples from previous articles that use application bundles.

  • The code for my tiling article is the most comprehensive sample. It has code to load a texture and load a data file using the Resource Manager. The functions GameLevel::ReadLevelData() and GameTexture::ReadFromFile() are the functions of interest.
  • The code for my QuickTime audio article is the simplest sample, providing an example of loading an audio file.
  • The code for my texture loading article provides a simple example of loading a graphics file from an application bundle.

Sorry, I currently don’t have any Cocoa or File Manager examples.

For more information on application bundles, refer to Apple’s Bundle Programming Guide.

Previous (Creating Bundles)