天天看點

第十五章檔案加載與儲存

Cocoa提供了Core Data,他能在背景處理所有檔案内容

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檔案,可以使用Xcode自帶的屬性清單編輯器編輯

有些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

                方法,方法複制自身屬性時,可以對其他對象也進行編碼