Friday, January 21, 2011

データの保存 (3) - ファイルやディレクトリの操作

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

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

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

ファイルやディレクトリの操作

ファイルやディレクトリの操作にはNSFileManagerを利用します。

NSFileManagerはファイルやディレクトリの作成・削除・移動・複製・一覧や、属性の取得や編集、シンボリックリンクの操作など様々なことを行えます。

この記事の内容
  • ディレクトリの作成
  • ファイルやディレクトリの削除
  • ファイルやディレクトリの移動
  • ファイルやディレクトリの存在確認
  • ファイルのアクセス権
  • ディレクトリの中身を調べる
  • スレッドセーフティー
ディレクトリの作成

ディレクトリを作成するには createDirectoryAtPath:withIntermediateDirectories:attributes:error: を使用します。

// NSFileManagerを取得 (非スレッドセーフ)
NSFileManager *fileManager = [NSFileManager defaultManager];
// パス
NSString *directoryPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample"];

// ディレクトリを作成
[fileManager createDirectoryAtPath: directoryPath // (NSString*) 作成したいディレクトリパス
       withIntermediateDirectories: YES           // (BOOL) 中間ディレクトリが存在しないときに作成するか否か
                        attributes: nil           // (NSDictionary*) ディレクトリの属性
                             error: NULL];        // (NSError**) エラー
ファイルやディレクトリの削除

ファイルやディレクトリの削除には removeItemAtPath:error: を使用します。

Note: このメソッドでディレクトリを削除すると、内包するファイルやサブディレクトリ、リンク等も全て削除されます。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *itemPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample"];

// ファイルやディレクトリの削除
[fileManager removeItemAtPath: itemPath // (NSString*) 削除したいアイテムのパス
                        error: NULL];   // (NSError**) エラー
ファイルやディレクトリの移動

ファイルやディレクトリの移動には moveItemAtPath:toPath:error: を使用します。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *sourcePath      = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"source"];
NSString *destinationPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"destination"];

// ファイルやディレクトリの移動
[fileManager moveItemAtPath: sourcePath      // (NSString*) 移動したいアイテムのパス
                     toPath: destinationPath // (NSString*) 移動先のパス
                      error: NULL];          // (NSError**) エラー
ファイルやディレクトリの存在確認

ファイルやディレクトリの存在をチェックするには fileExistsAtPath:isDirectory: を使用します。

Tips: ファイルとディレクトリの判別が不要であれば fileExistsAtPath: が使用できます。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *itemPath = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];
BOOL isDir;

// ファイルが存在
NSString *filePath = [itemPath stringByAppendingPathComponent:@"sample1"];
BOOL fileExists = ([fileManager fileExistsAtPath:filePath isDirectory:&isDir] && !isDir);

// ディレクトリが存在
NSString *directoryPath = [itemPath stringByAppendingPathComponent:@"sample2"];
BOOL directoryExists = ([fileManager fileExistsAtPath:directoryPath isDirectory:&isDir] && isDir);
ファイルのアクセス権

ファイルが読み出し可能であるか、書き込み可能であるかなどをチェックするには以下のメソッドを使用します。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample.txt"];

// 読み出し可能
BOOL readable   = [fileManager isReadableFileAtPath:filePath];
// 書き込み可能
BOOL writable   = [fileManager isWritableFileAtPath:filePath];
// 実行可能
BOOL executable = [fileManager isExecutableFileAtPath:filePath];
// 削除可能
BOOL deletable  = [fileManager isDeletableFileAtPath:filePath];
ディレクトリの中身を調べる

ディレクトリに内包されるファイルやサブディレクトリの一覧を取得するには、用途に応じていくつかの方法があります。

Note: 以下に示すメソッドはすべて現在のディレクトリ(.)、親ディレクトリ(..)、リソースフォーク(._で始まるファイル)を除いた値を返します。

浅い調査

contentsOfDirectoryAtPath:error: を利用すると、ディレクトリ内のファイル・サブディレクトリの一覧を配列形式で取得できます。サブディレクトリの中身は含まれません。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *directoryPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample"];

NSArray *contents = [fileManager contentsOfDirectoryAtPath: directoryPath // (NSString*) 走査したいディレクトリのパス
                                                     error: NULL];        // (NSError**) エラー
深い調査

サブディレクトリの中身も含めた一覧を取得するには subpathsOfDirectoryAtPath:error: を利用します。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *directoryPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample"];

NSArray *contents = [fileManager subpathsOfDirectoryAtPath: directoryPath // (NSString*) 走査したいディレクトリのパス
                                                     error: NULL];        // (NSError**) エラー
列挙

ディレクトリの内容を列挙したいときは enumeratorAtPath: を利用します。サブディレクトリの内容も含まれます。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *directoryPath = [[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] stringByAppendingPathComponent:@"sample"];

NSDirectoryEnumerator *directoryEnumerator = [fileManager enumeratorAtPath:directoryPath];
スレッドセーフティー

defaultManagerで取得したインスタンスはスレッドセーフではありません。

// 非スレッドセーフ
NSFileManager *fileManager = [NSFileManager defaultManager];

マルチスレッドで利用する場合はalloc+initでインスタンスを生成してください。

// スレッドセーフなNSFileManager
NSFileManager *fileManager = [[NSFileManager alloc] init];

// 使い終わったらrelease
[fileManager release];
参考サイト

次回

次の記事では「いろいろなデータのファイル保存」を取り上げます。

No comments:

Post a Comment