Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Objective-C.Programming.pdf
Скачиваний:
14
Добавлен:
21.02.2016
Размер:
8.64 Mб
Скачать

Reading files with NSString

Why not? You want to avoid creating an unnecessary error object if there’s no error. If there is an error, writeToFile:atomically:encoding:error: will be responsible for creating a new NSError instance and then modifying the error pointer you declared to point to the new error object. Then you can ask that object what went wrong via your error pointer.

This conditional creation of the NSError requires you to pass a reference to error (&error) because there’s no object yet to pass. However, unlike the passing by reference you did in Chapter 9 where you passed the reference of a primitive C variable, here you’re passing the address of a pointer variable. In essence, you’re passing the address of another address (which may become the address of an NSError object).

To revisit our international espionage analogy from Chapter 9, you might tell your spy, “If anything goes wrong, make a complete report (much too large to put in the steel pipe) and hide it in a book at the library. I need to know where you hid it, so put the call number of the book in the steel pipe.” That is, you are giving the spy a location where she can put the address of an error report she created.

Here’s a look inside the NSString class where writeToFile:atomically:encoding:error: is declared:

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile

encoding:(NSStringEncoding)enc error:(NSError **)error

Notice the double asterisk. When you call this method, you are supplying a pointer to a pointer to an instance of NSError.

Methods that pass an NSError by reference always return a value that indicates whether there was an error or not. This method, for example, returns NO if there is an error. Don’t try to access the NSError unless the return value indicates that an error occurred; if the NSError object doesn’t actually exist, trying to access it will crash your program.

Reading files with NSString

Reading a file into a string is very similar:

#import <Foundation/Foundation.h>

 

int main (int argc, const char * argv[])

{

@autoreleasepool {

 

NSError *error = nil;

NSString *str = [[NSString alloc] initWithContentsOfFile:@"/etc/resolv.conf" encoding:NSASCIIStringEncoding

error:&error];

if (!str) {

NSLog(@"read failed: %@", [error localizedDescription]); } else {

NSLog(@"resolv.conf looks like this: %@", str);

}

}

return 0;

}

153

Chapter 23 Writing Files with NSString and NSData

Writing an NSData object to a file

An NSData object represents a buffer of bytes. For example, if you fetch some data from a URL, you get an instance of NSData. And you can ask an NSData to write itself to a file. Create a new Foundation Command Line Tool named ImageFetch that fetches an image from the Google website into an instance of NSData. Then ask the NSData to write its buffer of bytes to a file:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

NSURL *url = [NSURL URLWithString: @"http://www.google.com/images/logos/ps_logo2.png"];

NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSError *error = nil;

NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL

error:&error];

if (!data) {

NSLog(@"fetch failed: %@", [error localizedDescription]); return 1;

}

NSLog(@"The file is %lu bytes", [data length]);

BOOL written = [data writeToFile:@"/tmp/google.png" options:0

error:&error];

if (!written) {

NSLog(@"write failed: %@", [error localizedDescription]); return 1;

}

NSLog(@"Success!");

}

return 0;

}

Build and run the program. Open the resulting image file in Preview.

Note that the writeToFile:options:error: method takes a number that indicates options to be used in the saving process. The most common option is NSDataWritingAtomic. Let’s say that you’ve already fetched an image, and you’re just re-fetching and replacing it with a newer version. While the new image is being written, the power goes off. A half-written file is worthless. In cases where a halfwritten file is worse than no file at all, you can make the writing atomic. Add this option:

NSLog(@"The file is %lu bytes", [data length]);

BOOL written = [data writeToFile:@"/tmp/google.png" options:NSDataWritingAtomic

error:&error];

154

Reading an NSData from a file

if (!written) {

NSLog(@"write failed: %@", [error localizedDescription]); return 1;

}

Now, the data will be written out to a temporary file, and, when the writing is done, the file is renamed the correct name. This way, you either get the whole file or nothing.

Reading an NSData from a file

You can also create an instance of NSData from the contents of a file. Add two lines to your program:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

@autoreleasepool {

NSURL *url = [NSURL URLWithString: @"http://www.google.com/images/logos/ps_logo2.png"];

NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSError *error;

// This method will block until all the data has been fetched NSData *data = [NSURLConnection sendSynchronousRequest:request

returningResponse:NULL

error:&error];

if (!data) {

NSLog(@"fetch failed: %@", [error localizedDescription]); return 1;

}

NSLog(@"The file is %lu bytes", [data length]);

BOOL written = [data writeToFile:@"/tmp/google.png" options:NSDataWritingAtomic

error:&error];

if (!written) {

NSLog(@"write failed: %@", [error localizedDescription]); return 1;

}

NSLog(@"Success!");

NSData *readData = [NSData dataWithContentsOfFile:@"/tmp/google.png"]; NSLog(@"The file read from the disk has %lu bytes", [readData length]);

}

return 0;

}

Build and run the program.

155

This page intentionally left blank

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]