标准C函数库提供了函数调用来创建、读取和写入文件,例如open()、write()、fopen()和fread()。
Cocoa提供了两个通用的文件处理类:属性列表和对象编码。
1、属性列表
在Cocoa中,有一类名为属性列表的对象,常简写为plist。这些列表包含Cocoa知道如何操作的一组对象。
Cocoa知道如何将它们保存到文件中并进行加载。
属性列表类包括NSArray、NSDictionary、NSString、NSNumber、NSData和NSDate,以及它们的变体(如果存在)。
1.1、NSDate
NSDate是Cocoa中用于处理日期和时间的基础类。
可以使用 [NSDate date] 获取当前的日期和时间,它是一个自动释放对象。
可以使用一些方法比较两个日期,从而对列表进行排序。还可以获取与当前时间相隔一定时差的日期。
NSDate *yesterday=[NSDate dateWithTimeIntervalSinceNow: -(20*60*60)];
+dateWithTimeIntervalSinceNow: 接受一个NSTimeInterval参数,该参数是一个双精度值表示以秒为单位的时间间隔。通过该参数可以指定时间偏移的方式:对于将来的时间,使用正的时间间隔;对于过去的时间,使用负的时间间隔。
1.2、NSData
将数据缓冲区传递给函数是C中的常见操作。通常配合缓冲区指针和长度一起使用。
Cocoa提供了NSData类,该类包装了大量字节。可以获得数据的长度和指向字节起始位置的指针。因为NSData是一个对象,适用于常规的内存管理行为。
如果将数据块传递给一个函数或方法,可以通过传递一个自动释放NSData来实现,无需担心内存清除问题。
NSData *data=[NSData dataWithBytes: string
length: strlen(string) + 1];
length方法给出字节数。bytes方法给出指向字符串起始位置的指针。
[data length];
[data bytes];
NSData对象是不可变的。它们被创建后就不能改变。可以使用它们,但不能更改其中的内容。
NSMutableData支持在数据内容中添加和删除字节。
1.3、写入和读取属性列表
集合属性列表类(NSArray、NSDictionary)具有一个 writeToFile: atomically: 方法,用于将属性列表写入文件。
NSString和NSData也具有writeToFile: atomically: 方法,但它只能写出字符串或数据块。
有些属性列表文件(特别是首选项文件)是以压缩的二进制格式存储的。通过使用plutil命令,可以将这些文件转换成可读的形式。
使用+arrayWithContentsOfFile: 方法读取该文件。
NSArray *phrase2=[NSArray arrayWithContentsOfFile: @"/tmp/a.txt"]
writeToFile: 方法中的单词atomically。它是BOOL类型值,用于通知Cocoa是否应该首先将文件内容保存在临时文件中。当文件成功保存后再降临时文件和原始文件交换。
2、编码对象
无法总是将对象信息表示为属性列表类。Cocoa具有一种机制来将对象自身转换为某种格式并保存到磁盘中。对象可以将它们的实例变量和其它数据编码为数据块,然后保存到磁盘中。以后将这些数据块读到内存中。并且还能基于保存的数据创建新对象。这个过程称为编码和解码,或称为序列化和反序列化。
NSCoding协议,包含方法encodeWithCoder和initWithCoder。
@protocol NSCoding
- (void) encodeWithCoder: (NSCoder *) aCoder;
- (id) initWithCoder: (NSCoder *) aDecoder;
@end
encodeWithCoder方法作为解码调用;
initWithCoder方法作为编码调用。
这两个方法的参数是 NSCoder 类型,可以调用encodeObject、encodeInt、encodeFloat等。
[coder encodeObject: name forKey: @"name"];
将name编码,作为字典的”name"键的值。
每种类型都有不同的encodeSomething: forKey: 。对于OC对象类型,都可以使用encodeObject: froKey: 。
如果需要回复某个对象,可以使用decodeSomethingForKey: 。
initWithCoder与其它init方法一样,在对对象执行操作之前,需要使用超类对它们进行初始化。
如果父类采用了NSCoding协议,则应该调用[super initWithCoder: decoder];否则,只需要调用[super init]即可。
NSObject不采用NSCoding协议。