Cocoa提供了兩個通用的文件處理類:屬性列表和對象編碼
一、屬性列表類
在Cocoa中,有一類名爲屬性列表的對象,簡寫爲plist。
這些列表包含Cocoa操作的一組對象,Cocoa知道如何將他們保存到文件中並進行加載
屬性列表類包括:NSArray、NSDictionary、NSString、NSNumber、NSDate和NSData以及他們的變體
1.NSDate
NSDate是Cocoa中用於處理日期和時間的基礎類
[NSDate date]獲取當前的日期和時間,它是自動釋放對象
+dateWithTimeIntervalSinceNow:(NSTimeInterval *)獲取與當前時間相隔的時間差
NSTimeInterval是一個雙精度參數,表示以秒爲單位的時間間隔,正數爲將來的時間,負數爲過去的時間
舉例代碼:
NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow: -(24 * 60 * 60)];
2.NSData
NSData類包含大量字節,可以獲得數據的長度和指向字節起始位置的指針
NSData是一個對象,適用於常規的內存管理行爲,可以寫成自動釋放對象
NSData是不可改變的,被創建後就不能改變,可以使用但不能更改其中內容
NSMutableData支持在數據內容中添加和刪除字節
舉例代碼:
NSData *data =[NSData dataWithBytes:string
length:strlen(string)+1];
3.寫入和讀取屬性列表
(1)寫入
集合屬性列表類(NSArray、NSDictionary)具有一個-writeToFile:atomically;方法用於將屬性列表寫入文件
NSString和NSData也具有writeToFile:atomically方法,但只能寫出字符串或數據塊,所以可以寫入數組然後再保存數組
舉例代碼:
NSArray *phrase;
phrase = [NSArray arrayWithObjects:@"I",@"AM",@"DE",@"WEI",@"I'M ",@"29",@"YEARS",@"OLD",nil];
[phrase writeToFile:@"/tmp/xxxxx.plist" atomically:YES];
Tip:atomically爲YES時保存過程中會佔用雙倍的硬盤空間來保存文件
有些plist文件是以二進制壓縮保存的,可以使用plutil -convert xml1 filename.plist轉換一下再閱讀
(2)讀取
使用-arrayWithContentsOfFile方法讀取文件(因爲只能用數組保存所以返回的也會是數組)
舉例代碼:
NSArray *phrase = [NSArray arrayWithContentsOfFile:@"tmp/xxx.plist"];
NSLog(@"%@",phrase);
(3)最簡單的保存可使用NSData的writeToFile:atomically轉換
不過這個方法不返回任何錯誤信息,如果不能加載文件只能得到nil指針,不能確定出現了何種錯誤
二、編碼對象
將對象自身的實例變量和其他數據編碼爲數據塊保存到磁盤,或者將數據塊度回到內存並基於數據創建新對象,稱爲序列化和反序列化 等價於 編碼和解碼
對於任何Objective-C都是用encodeObject:forKey;進行編碼
恢復某個對象,可以使用decodeSomethingForKey方法
如果對象不是屬性列表類型,則採用NSCoding協議和實現方法來編碼和解碼對象
採用NSCoding協議意味着必須實現encodeWithCoder和initWithCoder方法
舉例代碼:
#import <Foundation/Foundation.h>
@interface Thingie : NSObject <NSCoding> {
NSString *name;
int magicNumber;
float shoeSize;
NSMutableArray *subThingies;
}
@property (copy) NSString *name;
@property intmagicNumber;
@property float shoeSize;
@property (retain) NSMutableArray *subThingies;
- (id)initWithName: (NSString *) n
magicNumber: (int) mn
shoeSize: (float) ss;
@end // Thingie
@implementationThingie
@synthesize name;
@synthesizemagicNumber;
@synthesize shoeSize;
@synthesizesubThingies;
- (id)initWithName: (NSString *) n
magicNumber: (int) mn
shoeSize: (float) ss {
if (self = [super init]) {
self.name = n;
self.magicNumber = mn;
self.shoeSize = ss;
self.subThingies = [NSMutableArray array];
}
return (self);
}
- (void) dealloc {
[name release];
[subThingies release];
[super dealloc];
} // dealloc
- (void) encodeWithCoder: (NSCoder *) coder {
[coder encodeObject: name
forKey: @"name"];
[coder encodeInt: magicNumber
forKey: @"magicNumber"];
[coder encodeFloat: shoeSize
forKey: @"shoeSize"];
[coder encodeObject: subThingies
forKey: @"subThingies"];
} // encodeWithCoder
- (id) initWithCoder: (NSCoder *) decoder {
if (self = [super init]) {
self.name = [decoder decodeObjectForKey: @"name"];
self.magicNumber = [decoder decodeIntForKey: @"magicNumber"];
self.shoeSize = [decoder decodeFloatForKey: @"shoeSize"];
self.subThingies = [decoder decodeObjectForKey: @"subThingies"];
}
return (self);
} // initWithCoder
- (NSString *) description {
NSString*description =
[NSString stringWithFormat: @"%@: %d/%.1f %@",
name, magicNumber, shoeSize, subThingies];
return(description);
} // description
@end // Thingie
使用NSKeyArchiver把對象歸檔到NSData中,
keyedArchiver使用鍵/值對保存對象的信息
archivedDataWithRootObject方法,先在後臺創建一個NSKeyedArchiver實例,然後將實例傳遞給-encodeWithCoder
方法,方法複製自身屬性時,可以對其他對象也進行編碼