Tips

Objective-C フォルダ作成 NSFileManager 【初級編 第26回】

NSFileManagerによるフォルダ作成

ディレクトリの操作 その2

前回Objective-C ファイル存在確認 NSFileManager 【初級編 第25回】ではファイルの存在確認を行いました。
今回はそれ以外の機能についてみていきたいと思います。

ファイル・ディレクトリの作成

NSFileManagerを使用したファイル・ディレクトリの作成について見てみます。
ディレクトリの作成を行うには「createDirectoryAtPath:withIntermediateDirectories:attributes:error」メソッドを
使用します。
この「createDirectoryAtPath」メソッドは「NSFileManager.m」ファイル内で以下のように宣言されています。

- (BOOL) createDirectoryAtPath: (NSString *)path
   withIntermediateDirectories: (BOOL)flag
            attributes: (NSDictionary *)attributes
                         error: (NSError **) error;
- (BOOL) createDirectoryAtPath: (NSString*)path
            attributes: (NSDictionary*)attributes;

アップルのリファレンスを確認するとディレクトリ作成メソッドの下(引数2つの方です)のメソッドはMac OS Xv10.5から
推奨しないとなっているので、上のメソッドを利用することにします。

まず第1引数はディレクトリを作成するパスをNSString型のオブジェクトで指定します。
第2引数は第1引数で指定したパスのディレクトリがなかった場合、中間のディレクトリを作成するどうかをしています。
例えば第1引数で「./mydir/testdate」と指定していたとします。その時カレントディレクトリに「mydir」がないと
「testdate」は作成されませんが、この第2引数に「YES」を指定すると「mydir」を作成してその配下に「testdate」を
作成してくれます。
第3引数は作成されたディレクトリの属性の設定を行う時に使用します。ここで「nil」を指定するとデフォルトの属性値が
設定されるようになっています。
NSDictionaryクラスはオブジェクトの集合を管理するものとなります。NSArrayとの違いは、添え字で管理している
NSArrayに対して、キー名で中のオブジェクトを管理することができます。
第4引数は前に出てきたとおりエラーの情報を管理するために使用されるクラスを指定します。

ファイルの作成の方は「createFileAtPath:contents:attributes」メソッドを使用します。

- (BOOL) createFileAtPath: (NSString*)path
         contents: (NSData*)contents
         attributes: (NSDictionary*)attributes;

まず第1引数はファイルを作成するパスをNSString型のオブジェクトで指定します。
第2引数はファイル内に書き込む中身を指定します。NSDataはバイナリデータの格納を行うための
第3引数はディレクトリのところと同様にファイルの属性を指定する際に使用されるものとなります。

ファイルの移動 コピー

NSFileManagerを使用したファイルの移動を行うには「moveItemAtPath」メソッドを使用します。
このメソッドは「NSFileManager.m」ファイル内で以下のように宣言されています。

- (BOOL) moveItemAtPath: (NSString*)src toPath: (NSString*)dst error: (NSError**)error

第1引数は移動したいファイルのパスをNSString型のオブジェクトで指定します。
第2引数は移動先のパスをNSString型のオブジェクトで指定します。
第3引数はエラーの情報を管理するために使用されるクラスを指定します。

続いてコピーの方です。

- (BOOL) copyItemAtPath: (NSString*)src toPath: (NSString*)dst error: (NSError**)error

引数は移動と同じとなります。

コードでの確認

先ほど紹介した、メソッドのうちディレクトリ作成とファイル移動を実際使用してみましょう。
前回のコードでデータの読み取りをしていましたので、データ読み取りが済んだファイルに関しては別のディレクトリに
移動させることにします。
元のデータの入っているディレクトリを「data」、移動先のディレクトリを「old」となるようにしています。

main.m

#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>
#import "Bmi.h"
#import "Person.h"
#import "Manage.h"

int main(int argc, const char *argv[]){

    Person *person = nil;
    int i,j;
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSError *error=nil;
    NSString *dataPath = @"./data/";
    NSString *destinationPath = @"./old/";
    BOOL isDir = NO;

    Manage *manage = [[Manage alloc] init];
    NSFileManager *filemanager = [ NSFileManager defaultManager];
    //ディレクトリの確認
    if(![filemanager fileExistsAtPath:destinationPath isDirectory:&isDir]){
        //ディレクトリ作成
         [filemanager createDirectoryAtPath:destinationPath
         withIntermediateDirectories:YES
         attributes:nil error:&error];
    }
    //ディレクトリの確認
    if([filemanager fileExistsAtPath:dataPath isDirectory:&isDir]){
        if( isDir == YES ){
            printf("ディレクトリです。n");
        }else{
            printf("ファイルです。n");
            return 0;
        }
    }else{
        printf("ディレクトリが見つかりません。n");
        return 0;
    }
    NSArray *files = [filemanager contentsOfDirectoryAtPath:dataPath error:&error];
    for( i = 0; i < [files count]; i++){
        NSString *sourceFile = [dataPath stringByAppendingString:[files objectAtIndex:i]];
        NSString *destinationFile = [destinationPath stringByAppendingString:[files objectAtIndex:i]];
        printf("file --%s--n",[sourceFile UTF8String]);
        NSString *file = [NSString stringWithContentsOfFile:sourceFile
                                encoding:NSUTF8StringEncoding
                                error:&error ];
        NSArray *line = [file componentsSeparatedByString:@"n"];
        for(j = 0; j < [line count]; j++){
            if( [[line objectAtIndex:j] isEqualToString:@""]) {
                continue;
            }
            NSArray *col = [[line objectAtIndex:j] componentsSeparatedByString:@" "];
            person = [[Person alloc] initWithWeight:[[col objectAtIndex:1] doubleValue]
                                     height:[[col objectAtIndex:2] doubleValue]
                                     name:[col objectAtIndex:0]];
            [manage setPerson:person];
            [person release];
        }
       //処理が終了したので終了済みのディレクトリにファイルを移動
        [filemanager moveItemAtPath:sourceFile toPath:destinationFile error:&error];
    }
    [manage showBestPerson];
    [manage recordBestPerson];
    [manage release];
    [pool drain];
    return 0;
}

全体的な流れとしてはまず移動先のディレクトリを作成しています。
そしてデータの入ったディレクトリを検索後に内部のデータを読み取り、
最後に処理済みのファイルを最初に作成したディレクトリに移動というものとなっています。

前回からの変更点としては14行目で読み取り済みのデータを保存するパスを表すNSStringオブジェクトを作成しています。
20行目で移動先のディレクトリを作成する前にすでにディレクトリが作成されているかどうかの確認を行っています。

22行目はディレクトリが存在しない場合に行われる処理で、ディレクトリの作成を行っています。

41行目では同一ファイル名で移動させるために移動先のパスとファイル名を結合しています。

56行目で実際のコピーをしています。第1引数でコピー元ファイル名と指定し、第2引数でコピー先ファイル名を指定
しています。

結果確認

Objc26-1

プログラム自体の実行結果の表示は変わりませんが、実行後のディレクトリ情報をみるとファイルが移動されていると
思います。

NSFileManagerで使用できるメソッドはこれ以外にもありますので、クラスリファレンスなどで確認してみてください。
Mac OS Xv10.5から推奨しないとなっているメソッドについても記載されています。

まとめ

今回のまとめとしては
・NSFileManagerを使用してファイルやディレクトリの作成や移動・コピーができる
・Mac OS Xv10.5では推奨されていないメソッドもこのクラスには結構あるので気を付けてください
といったところでしょうか。

TechProjin 開発系基礎講座 連載リンク

基礎からPHPWEBアプリ解発を学ぶなら・・
PHP基礎 連載

AIなどで注目急上昇!これから学ぶならPython!!
独学で学ぶ-pythonプログラミング 連載

汎用性◎ 定番プログラミング言語JAVA
Java基礎講座 連載

Recent News

Recent Tips

Tag Search