Changes

Working with Files in Objective-C

4,635 bytes added, 16:31, 11 November 2009
no edit summary
NSLog (@"Remove failed");
</pre>
 
== Reading and Writing Files with NSFileManager ==
 
The NSFileManager class includes some basic file reading and writing capabilities. these capabilities are somewhat limited when compared to the options provided by the NSFileHandle class, but can be useful for nonetheless.
 
Firstly, the contents of a file may be read and stored in an NSData object through the use of the ''contentsAtPath'' method:
 
<pre>
NSFileManager *filemgr;
NSData *databuffer;
 
filemgr = [NSFileManager defaultManager];
 
databuffer = [filemgr contentsAtPath: @"/tmp/myfile.txt" ];
</pre>
 
Having stored the contents of a file in an NSData object, that data may subsequently be written out to a new file using the ''createFileAtPath'' method:
 
<pre>
databuffer = [filemgr contentsAtPath: @"/tmp/myfile.txt" ];
 
[filemgr createFileAtPath: @"/tmp/newfile.txt" contents: databuffer attributes: nil];
</pre>
 
In the above example we have essentially copied the contents from an existing file to a new file. This, however, gives us no control over how much data is to be read or written and does not allow us to append data to the end of an existing file. If the file ''/tmp/newfile.txt'' in the above example had already existed it, and any data it contained, would have been overwritten by the contents of the source file. Clearly some more flexible mechanism is required. This is provided by the Foundation Framework in the form of the ''NSFileHandle'' class.
 
== Working with Files using the NSFileHandle Class ==
 
The NSFileHandle class provides a range of methods designed to provide a more advanced mechanism for working with files. In addition to files, this class can also be used for working with devices and network sockets. In the following sections we will look at some of the more common uses for this class.
 
== Creating an NSFileHandle Object ==
 
An NSFileHandle object can be created when opening a file for reading, writing or updating (reading and writing). This is achieved using the ''fileHandleForReadingAtPath'', ''fileHandleForWritingAtPath'' and ''fileHandleForUpdatingAtPath'' respectively. Having opened a file, it must subsequently be closed when we have finsihed working with it using the ''closeFile'' method. If an attempt to open a file fails, for example because an attempt is made to open a non-existent file reading, these methods return ''nil''.
 
For example, the following code excerpt opens a file for reading and writing and then closes it without actually doing anything to the file:
 
<pre>
NSFileHandle *file;
 
file = [NSFileHandle fileHandleForWritingAtPath: @"/tmp/myfile.txt"];
 
if (file == nil)
NSLog(@"Failed to open file");
 
[file closeFile];
</pre>
 
== NSFileHandle File Offsets and Seeking ==
 
NSFileHandle objects maintain a pointer to the current position in a file. This is referred to as the ''offset''. When a file is first opened the offset is set to 0. This means that any read or write operations we perform using the NSFileHandle methods will take place at offset 0 in the file. To perform operations at different locations in a file (for example to append data to the end of the file) it is first necessary to ''seek'' to the required offset. For example to move the current offset to the end of the file, use the ''seekToEndOfFile'' method. Alternatively, ''seekToFileOffset'' allows you to specifiy the precise location in the file to whichthe offset is to be position. Finally, the current offset may be identified using the ''offsetInFile'' method. in order to accommodate large files, the offset is stored in the form of an unsigned long long.
 
The following example opens a file for reading and then performs a number of method calls to move the offset to different positions, outputting the current offset after each move:
 
<pre>
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/myfile.txt"];
 
if (file == nil)
NSLog(@"Failed to open file");
 
NSLog (@"Offset = %llu", [file offsetInFile]);
 
[file seekToEndOfFile];
 
NSLog (@"Offset = %llu", [file offsetInFile]);
 
[file seekToFileOffset: 30];
 
NSLog (@"Offset = %llu", [file offsetInFile]);
 
[file closeFile];
</pre>
 
File offsets are a key aspect of working with files using the NSFileHandle class so it is worth taking extra time to make sure you understand the concept. Without knowing where the current offset is in a file it is impossible to know where in the file data will be read or written.
 
== Reading Data from a File ==
 
Once a file has been opened and assigned a file handle, the contents of that file may be read either in its entirety, or as a specified number of bytes starting at any location in the file.