文件程式最重要的就是能存取檔案. 根據檔案的複雜度, 有數種 methods 可以實作.
表格 13.1. 存取檔案的 Methods
讀取檔案 | 儲存檔案 | |
高階 (簡單) | loadDataRepresentation:ofType: | dataRepresentationOfType: |
中階 | loadFileWrapperRepresentation:ofType: | fileWrapperRepresentationOfType: |
低階 | readFromFile:ofType:, readFromURL:ofType: | writeToFile:ofType:, writeToURL:ofType: |
可參考 How do I implement saving and loading for simple files?, How do I implement document packages (documents that are really folders, but appear to be opaque documents)?, 以及 How do I implement loading and saving when the simple data or file wrapper API won't do?.
在這個簡單的例子中, 使用高階的 -loadDataRepresentation:ofType: and -dataRepresentationOfType: 便足夠了.
Document.m:
- (NSData *) dataRepresentationOfType: (NSString *) type { if (type == nil) type = @"mon"; if ([type isEqualToString: @"mon"]) return [NSArchiver archivedDataWithRootObject: records]; else return nil; } - (BOOL) loadDataRepresentation: (NSData *) data ofType: (NSString *) type { if ([type isEqualToString: @"mon"]) { [records setArray: [NSUnarchiver unarchiveObjectWithData: data]]; return YES; } return NO; }
當使用者要存檔時, 會呼叫 -dataRepresentationOfType:. type 即是程式屬性檔 (MoneyInfo.plist) 中的 NSName. 在這裡使用 NSArchiver 將整個物件轉成 NSData, 至於其內部結構則不用理會. 當使用者要開啟檔案時, 會呼收 -loadDataRepresentation:ofType:. 這時使用 NSUnarchiver 將整個 NSData 轉換回 NSArray. 如此便完成了讀存檔的功能. 如果想將檔案存成特定格式, 那就必需自行處理資料結構的問題. 可參考 data archives 及 Using the Property List Objects and the NSCoding Protocol.
使用 NSArchiver 存成的檔案是位元檔, 而不是文字檔. 因此不能使用一般的文字編輯器來修改, 在資料的交換上其實不太方便. 因為 NSArray 及 NSDictionary 都是簡單的資料結構, 可以轉換成屬性檔 (property list), 這時就是一般可處理的文字檔格式了.
Document.m:
- (NSData *) dataRepresentationOfType: (NSString *) type { if (type == nil) type = @"mon"; if ([type isEqualToString: @"mon"]) return [[records description] dataUsingEncoding: [NSString defaultCStringEncoding]]; else return nil; } - (BOOL) loadDataRepresentation: (NSData *) data ofType: (NSString *) type { if ([type isEqualToString: @"mon"]) { NSString *string = [[NSString alloc] initWithData: data encoding: [NSString defaultCStringEncoding]]; [records setArray: [string propertyList]]; RELEASE(string); return YES; } return NO; }
在這裡使用 -description 將資料結構轉成屬性檔, 其為一字串 (文字格式). 再將其字串轉成 NSData 即可. 反之用於讀檔. 如此便可將資料存成一般的文字檔. 只有簡單的資料結構可以存成屬性檔. 像是 NSCalendarDate, NSHost 等便不能存成屬字檔, 只能用 NSArchiver 轉成位元檔, 或是自行想辦法將其轉成文字檔.
程式碼在此: LoadSave-src.tar.gz.
如果要將文件存成一個目錄, 例如一個 HTML 文件包含了文字及圖檔, 都要放在同一個目錄, 可以使用 -loadFileWrapperRepresentation:ofType: and -fileWrapperRepresentationOfType:. -readFromFile:ofType: and -writeToFile:ofType: 則可直接接觸檔案系統, 可與 NSFileHandle 並用.