For the More Curious: Reading and Writing to the Filesystem

In addition to archiving and NSData’s binary read and write methods, there are a few more methods for transferring data to and from the filesystem. One of them, Core Data, is coming up in Chapter 23. A couple of others are worth mentioning here.

You have access to the standard file I/O functions from the C library. These functions look like this:

F​I​L​E​ ​*​i​n​F​i​l​e​ ​=​ ​f​o​p​e​n​(​"​t​e​x​t​f​i​l​e​"​,​ ​"​r​t​"​)​;​
c​h​a​r​ ​*​b​u​f​f​e​r​ ​=​ ​m​a​l​l​o​c​(​s​o​m​e​S​i​z​e​)​;​
f​r​e​a​d​(​b​u​f​f​e​r​,​ ​b​y​t​e​C​o​u​n​t​,​ ​1​,​ ​i​n​F​i​l​e​)​;​

F​I​L​E​ ​*​o​u​t​F​i​l​e​ ​=​ ​f​o​p​e​n​(​"​b​i​n​a​r​y​f​i​l​e​"​,​ ​"​w​"​)​;​
f​w​r​i​t​e​(​b​u​f​f​e​r​,​ ​b​y​t​e​C​o​u​n​t​,​ ​1​,​ ​o​u​t​F​i​l​e​)​;​

However, you will not see these functions used much because there are more convenient ways of reading and writing binary and text data. Using NSData works well for binary data. For text data, NSString has two instance methods writeToFile:atomically:encoding:error: and initWithContentsOfFile:. They are used as follows:

/​/​ ​A​ ​l​o​c​a​l​ ​v​a​r​i​a​b​l​e​ ​t​o​ ​s​t​o​r​e​ ​a​n​ ​e​r​r​o​r​ ​o​b​j​e​c​t​ ​i​f​ ​o​n​e​ ​c​o​m​e​s​ ​b​a​c​k​
N​S​E​r​r​o​r​ ​*​e​r​r​;​

N​S​S​t​r​i​n​g​ ​*​s​o​m​e​S​t​r​i​n​g​ ​=​ ​@​"​T​e​x​t​ ​D​a​t​a​"​;​
B​O​O​L​ ​s​u​c​c​e​s​s​ ​=​ ​[​s​o​m​e​S​t​r​i​n​g​ ​w​r​i​t​e​T​o​F​i​l​e​:​@​"​/​s​o​m​e​/​p​a​t​h​/​f​i​l​e​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​t​o​m​i​c​a​l​l​y​:​Y​E​S​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​n​c​o​d​i​n​g​:​N​S​U​T​F​8​S​t​r​i​n​g​E​n​c​o​d​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​r​r​o​r​:​&​e​r​r​]​;​
i​f​ ​(​!​s​u​c​c​e​s​s​)​ ​{​
 ​ ​ ​ ​N​S​L​o​g​(​@​"​E​r​r​o​r​ ​w​r​i​t​i​n​g​ ​f​i​l​e​:​ ​%​@​"​,​ ​[​e​r​r​ ​l​o​c​a​l​i​z​e​d​D​e​s​c​r​i​p​t​i​o​n​]​)​;​
}​

N​S​S​t​r​i​n​g​ ​*​m​y​E​s​s​a​y​ ​=​ ​[​[​N​S​S​t​r​i​n​g​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​C​o​n​t​e​n​t​s​O​f​F​i​l​e​:​@​"​/​s​o​m​e​/​p​a​t​h​/​f​i​l​e​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​n​c​o​d​i​n​g​:​N​S​U​T​F​8​S​t​r​i​n​g​E​n​c​o​d​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​r​r​o​r​:​&​e​r​r​]​;​
i​f​ ​(​!​m​y​E​s​s​a​y​)​ ​{​
 ​ ​ ​ ​N​S​L​o​g​(​@​"​E​r​r​o​r​ ​r​e​a​d​i​n​g​ ​f​i​l​e​:​ ​%​@​"​,​ ​[​e​r​r​ ​l​o​c​a​l​i​z​e​d​D​e​s​c​r​i​p​t​i​o​n​]​)​;​
}​

What is that NSError object? Some methods might fail for a variety of reasons. For example, writing to the filesystem might fail because the path is invalid or the user does not have permission to write to the specified path. An NSError object contains the reason for a failure. You can send the message localizedDescription to an instance of NSError for a human-readable description of the error. This is something you can show to the user or print to a debug console.

The syntax for getting back an NSError instance is a little strange. An error object is only created if an error occurred; otherwise, there is no need for the object. When a method can return an error through one of its arguments, you create a local variable that is a pointer to an NSError object. Notice that you do not instantiate the error object – that is the job of the method you are calling. Instead, you pass the address of your pointer variable (&err) to the method that might generate an error. If an error occurs in the implementation of that method, an NSError instance is created, and your pointer is set to point at that new object. If you do not care about the error object, you can always pass nil.

Sometimes you want to show the error to the user. This is typically done with a UIAlertView (Figure 18.10).

Figure 18.10  Example of UIAlertView

Example of UIAlertView

Creating a UIAlertView looks like this:

N​S​S​t​r​i​n​g​ ​*​x​ ​=​ ​[​[​N​S​S​t​r​i​n​g​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​C​o​n​t​e​n​t​s​O​f​F​i​l​e​:​@​"​/​s​o​m​e​/​p​a​t​h​/​f​i​l​e​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​n​c​o​d​i​n​g​:​N​S​U​T​F​8​S​t​r​i​n​g​E​n​c​o​d​i​n​g​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​r​r​o​r​:​&​e​r​r​]​;​
i​f​ ​(​!​x​)​ ​{​
 ​ ​ ​ ​U​I​A​l​e​r​t​V​i​e​w​ ​*​a​ ​=​ ​[​[​U​I​A​l​e​r​t​V​i​e​w​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​T​i​t​l​e​:​@​"​R​e​a​d​ ​F​a​i​l​e​d​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​m​e​s​s​a​g​e​:​[​e​r​r​ ​l​o​c​a​l​i​z​e​d​D​e​s​c​r​i​p​t​i​o​n​]​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​d​e​l​e​g​a​t​e​:​n​i​l​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​c​a​n​c​e​l​B​u​t​t​o​n​T​i​t​l​e​:​@​"​O​K​"​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​t​h​e​r​B​u​t​t​o​n​T​i​t​l​e​s​:​n​i​l​]​;​
 ​ ​ ​ ​[​a​ ​s​h​o​w​]​;​
}​

Note that in many languages, anything unexpected results in an exception being thrown. Among Objective-C programmers, exceptions are nearly always used to indicate programmer error. When an exception is thrown, the information about what went wrong is in an NSException object. That information is usually just a hint to the programmer like You tried to access the 7th object in this array, but there are only two. The symbols for the call stack (as it appeared when the exception was thrown) are also in the NSException.

When do you use NSException and when do you use NSError? If you are writing a method that should only be called with an odd number as an argument, throw an exception if it is called with an even number – the caller is making an error and you want to help that programmer find the error in his ways. If you are writing a method that wants to read the contents of a particular directory, but does not have the necessary privileges, create an NSError and pass it back to the caller to indicate why you were unable to fulfill this very reasonable request.

Like NSString, the classes NSDictionary and NSArray have writeToFile: and initWithContentsOfFile: methods. To write collection objects to the filesystem with these methods, the collection objects must contain only property list serializable objects. The only objects that are property list serializable are NSString, NSNumber, NSDate, NSData, NSArray, and NSDictionary. When an NSArray or NSDictionary is written to the filesystem with these methods, an XML property list is created. An XML property list is a collection of tagged values:

<​?​x​m​l​ ​v​e​r​s​i​o​n​=​"​1​.​0​"​ ​e​n​c​o​d​i​n​g​=​"​U​T​F​-​8​"​?​>​
<​!​D​O​C​T​Y​P​E​ ​p​l​i​s​t​ ​P​U​B​L​I​C​ ​"​-​/​/​A​p​p​l​e​/​/​D​T​D​ ​P​L​I​S​T​ ​1​.​0​/​/​E​N​"​
 ​ ​ ​ ​ ​ ​ ​"​h​t​t​p​:​/​/​w​w​w​.​a​p​p​l​e​.​c​o​m​/​D​T​D​s​/​P​r​o​p​e​r​t​y​L​i​s​t​-​1​.​0​.​d​t​d​"​>​
<​p​l​i​s​t​ ​v​e​r​s​i​o​n​=​"​1​.​0​"​>​
<​a​r​r​a​y​>​
 ​ ​ ​ ​<​d​i​c​t​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​f​i​r​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​C​h​r​i​s​t​i​a​n​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​l​a​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​K​e​u​r​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​<​/​d​i​c​t​>​
 ​ ​ ​ ​<​d​i​c​t​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​f​i​r​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​J​o​e​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​l​a​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​C​o​n​w​a​y​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​<​/​d​i​c​t​>​
 ​ ​ ​ ​<​d​i​c​t​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​f​i​r​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​A​a​r​o​n​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​k​e​y​>​l​a​s​t​N​a​m​e​<​/​k​e​y​>​
 ​ ​ ​ ​ ​ ​ ​ ​<​s​t​r​i​n​g​>​H​i​l​l​e​g​a​s​s​<​/​s​t​r​i​n​g​>​
 ​ ​ ​ ​<​/​d​i​c​t​>​
<​/​a​r​r​a​y​>​
<​/​p​l​i​s​t​>​

XML property lists are a convenient way to store data because they can be read on nearly any system. Many web service applications use property lists as input and output. The code for writing and reading a property list looks like this:

N​S​M​u​t​a​b​l​e​D​i​c​t​i​o​n​a​r​y​ ​*​d​ ​=​ ​[​N​S​M​u​t​a​b​l​e​D​i​c​t​i​o​n​a​r​y​ ​d​i​c​t​i​o​n​a​r​y​]​;​
d​[​@​"​S​t​r​i​n​g​"​]​ ​=​ ​@​"​A​ ​s​t​r​i​n​g​"​;​
[​d​ ​w​r​i​t​e​T​o​F​i​l​e​:​@​"​/​s​o​m​e​/​p​a​t​h​/​f​i​l​e​"​ ​a​t​o​m​i​c​a​l​l​y​:​Y​E​S​]​;​

N​S​M​u​t​a​b​l​e​D​i​c​t​i​o​n​a​r​y​ ​*​a​n​o​t​h​e​r​D​ ​=​ ​[​[​N​S​M​u​t​a​b​l​e​D​i​c​t​i​o​n​a​r​y​ ​a​l​l​o​c​]​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​i​n​i​t​W​i​t​h​C​o​n​t​e​n​t​s​O​f​F​i​l​e​:​@​"​/​s​o​m​e​/​p​a​t​h​/​f​i​l​e​"​]​;​

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset