Thursday, February 10, 2011

データの保存 (4) - いろいろなデータのファイル保存

iPhoneアプリ開発において、データを保存したい場合はどうすればいいのだろう?

今回は様々なデータ保存の手法を取り上げてみます。

バックナンバー
  1. 設定などの保存
  2. ホームディレクトリとファイルパス
  3. ファイルやディレクトリの操作
  4. いろいろなデータのファイル保存
  5. プロパティリストの利用
  6. ローレベルなファイルアクセス

いろいろなデータのファイル保存

さて、それでは今回の本題「データ保存」の方法を調べていきます。

一概にデータを保存するといっても、既存のクラスを利用して簡単に保存する方法もあれば、ファイルハンドルを取得してバイト列を読み書きするローレベルな方法もあります。
今回は前者の高レベルなアクセスを取り上げましょう。

この記事の内容
  • バイナリデータのファイル保存 (NSData)
  • 文字列のファイル保存 (NSString)
  • 配列や辞書のファイル保存 (NSArray, NSDictionary)
  • オブジェクトのシリアライズ (NSCoding)
バイナリデータのファイル保存 (NSData)

NSDataには writeToFile:atomically: および dataWithContentsOfFile: / initWithContentsOfFile: というメソッドが用意されています。
これらのメソッドを利用すると簡単にファイル保存・復帰(読み出し)ができます。

NSMutableDataなどNSDataのサブクラスもこれらのメソッドを利用し同様にアクセスできます。

Tips: atomicallyにYESを与えると、別名の予備ファイルにデータを書き込み完了後にリネームします。並列処理などでアクセスが競合したり、アプリケーションが異常終了したときにファイルが破損することを防ぎます。

NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample.binary"];
NSData *myData = [NSData data];

// 保存
[myData writeToFile: filePath  // (NSString *) ファイルパス
         atomically: YES];     // (BOOL) 予備ファイルを生成

// 読み込み
myData = [NSData dataWithContentsOfFile:filePath];  // (NSString *) ファイルパス
文字列のファイル保存 (NSString)

NSStringには writeToFile:atomically:encoding:error: および initWithContentsOfFile:encoding:error: などといったメソッドが用意されています。
サブクラス(NSMutableStringなど)も同様にこのメソッドが利用できます。

保存したファイルは純粋なテキストファイルとなります。

NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample.strings"];
NSString *myString = [NSString string];

// 保存
[myString writeToFile: filePath                 // (NSString *) ファイルパス
           atomically: YES                      // (BOOL) 予備ファイルを生成
             encoding: NSUnicodeStringEncoding  // (NSStringEncoding) 文字コード
                error: NULL];                   // (NSError **) エラー

// 読み込み
myString = [NSString stringWithContentsOfFile: filePath                 // (NSString *) ファイルパス
                                     encoding: NSUnicodeStringEncoding  // (NSStringEncoding) 文字コード
                                        error: NULL];                   // (NSError **) エラー
NSStringEncoding

以下にencodingで指定できる主な文字コードの定数を示します。

NSUnicodeStringEncoding / NSUTF16StringEncoding
Unicode 16bit (UTF-16)
NSUTF8StringEncoding
Unicode 8bit (UTF-8)
NSASCIIStringEncoding
ASCII 7bit
NSISO2022JPStringEncoding
ISO-2022-JP (JIS)
NSShiftJISStringEncoding
Shift_JIS
NSJapaneseEUCStringEncoding
EUC-JP
配列や辞書のファイル保存 (NSArray, NSDictionary)

NSArray、NSDictionaryにも writeToFile:atomically: および initWithContentsOfFile: などといったメソッドが用意されています。
サブクラス(NSMutableArray、NSMutableDictionaryなど)も同様にアクセスできます。

ファイルにはプロパティリスト形式のXMLとして保存されます。

Note: 配列および辞書に内包できるデータはプロパティリストに含められるもの (NSString, NSNumber, NSDate, NSData, NSArray, NSDictionary) のみです。それ以外のデータはNSCodingを利用(後述)するなどして他形式に変換したものを格納してください。

NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample.plist"];
NSDictionary *myDictionary = [NSDictionary dictionary];

// 保存
[myDictionary writeToFile: filePath  // (NSString *) ファイルパス
               atomically: YES];     // (BOOL) 予備ファイルを生成

// 読み込み
myDictionary = [NSData dictionaryWithContentsOfFile:filePath];  // (NSString *) ファイルパス
オブジェクトのシリアライズ (NSCoding)

独自クラスのインスタンスも保存できます。インスタンスを保存可能にするには、クラスにNSCodingプロトコルを実装します。

NSCodingを実装したクラスはNSKeyedArchiverNSKeyedUnarchiverなどを利用してNSDataに変換・インスタンスに復帰できます。
この変換したNSDataは通常のデータとして辞書や配列に格納したり writeToFile:atomically: で書き出すことも可能です。

NSCodingプロトコルの実装、シリアライズ・デシリアライズはこの記事の範疇から少し外れますので、他に詳しい記事をご紹介します。

参考サイト

次回

次の記事では「プロパティリストの利用」を取り上げる予定です。

No comments:

Post a Comment