File System Utilities
The File I/O classes consist of a collection of APIs for using files and directories. The classes enable you to represent file paths, perform basic operations with files and directories, find directories on the system, and use streams to perform input/output (I/O) operations with files, in-memory, or to/from a network resource.
Application Bundles
The NSBundle class groups code and resources that can be used in a program. They are used to locate program resources, dynamically load and unload executable code, and assist in localization. The NSBundleclass includes methods that enable you to create and initialize a bundle, retrieve a bundle or bundle class, load a bundle’s code, find resources in a bundle, retrieve bundle information, and manage localization. In Chapters 7 and 9, you learned about loadable bundles and used theNSBundle class to dynamically load a bundle and create an object from a bundle class, so you can refer to these chapters for further information and code examples.
File Management
The NSFileHandle class provides low-level file management utilities. AnNSFileHandle class instance is an object-oriented wrapper for a file descriptor. It includes methods for creating and initializing file handlers, retrieving a file descriptor, performing file I/O using a file handler, and closing a file when you are done. It also supports asynchronous file operations. Many of the NSFileHandle creation methods also acquire ownership of the file descriptor, and automatically close the file when the object is deallocated. The class also includes methods to create anNSFileHandle object with an input file descriptor. In these scenarios, thecloseFile method can be used to close the descriptor. Listing 11-5demonstrates the use of NSFileHandle APIs to read a file namedExample.txt from the system’s default location to store temporary files.
Listing 11-5. Using NSFileHandle to Read a File
NSString *tmpDir = NSTemporaryDirectory();
NSString *myFile = [NSString stringWithFormat:@"%@/%@", tmpDir,
@"Example.txt"];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:myFile];
if (fileHandle)
{
NSData *fileData = [fileHandle readDataToEndOfFile];
NSLog(@"%lu bytes read from file %@", [fileData length], myFile);
}
The NSFileManager class provides general-purpose methods for performing basic file-system operations. It includes methods to create a file manager, locate directories, query directory contents, manage file and directory items, create soft/hard links to files, query file access, get/set file system attributes, and even manage iCloud-storage items.Listing 11-6 uses the NSFileManager APIs to list the contents at the current directory path, and then query whether the first file found in this directory is executable.
Listing 11-6. Using NSFileManager to List the Contents of a Directory
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *currentPath = [filemgr currentDirectoryPath];
NSArray *contents = [filemgr contentsOfDirectoryAtPath:currentPath error:&error];
NSLog(@"Contents: %@", contents);
if (contents)
{
NSString *file = [NSString stringWithFormat:@"%@/%@", currentPath, contents[0]];
if ([filemgr isExecutableFileAtPath:file])
{
NSLog(@"%@ is executable", file);
}
}
Stream Input-Output
Streams provide a convenient mechanism for reading and writing data sequentially, whether that data be located in memory, a file, or over a network. The NSStream, NSInputStream, and NSOutputStream classes provide functionality for reading from/writing to streams. NSStream is an abstract class, and NSInputStream and NSOutputStream are its concrete subclasses. A stream can be read/written asynchronously (usually the preferred approach) or synchronously by polling. To access a stream asynchronously, a delegate object is set for the stream (i.e., anNSInputStream or NSOutputStream object) and the stream is then scheduled in a run loop. The delegate conforms to theNSStreamDelegate protocol. The run loop invokes itsstream:handleEvent: to handle stream events (status, data available, error conditions). Listing 11-7 demonstrates use of the NSInputStreamAPIs to create an input stream from a file, and then synchronously readdata from a file named Example.txt (stored in the current directory) into a buffer.
Listing 11-7. Using NSInputStream to Read a File
NSString *currentPath = [[NSFileManager defaultManager] currentDirectoryPath];
NSString *myFile = [NSString stringWithFormat:@"%@/%@", currentPath,
@"Example.txt"];
NSInputStream *ins = [NSInputStream inputStreamWithFileAtPath:myFile];
[ins open];
if (ins && [ins hasBytesAvailable])
{
uint8_t buffer[1024];
NSUInteger len = [ins read:buffer maxLength:1024];
NSLog(@"Bytes read = %lu", len);
}
After creating the input stream, the stream is opened. Next, the NSInputStream hasBytesAvailable method is used to determine whether the stream has any bytes to read, and if so, the NSInputStreamread method is used to read the data into a buffer. Finally, the number of bytes read is logged to the console.
Metadata Queries
The NSMetadataItem and NSMetadataQuery set of classes provide APIs for metadata queries that enable an application to search for files based on data that is part of the file or file system. Together they provide a programmatic way to perform file searches using file metadata, as provided with the Apple desktop Spotlight search tool.
The NSMetadataItem and NSMetadataQuery classes are available for use on the OS X platform only (i.e., this class is not available for the iOS platform).