Objective-C ファイル存在確認 NSFileManager 【初級編 第25回】


NSFileManagerによるファイル存在確認

NSFileManagerを使用したファイル操作

Objective-C ファイル操作 NSFileManager 【初級編 第24回】ではNSFileManagerを使用してディレクトリの検索を
行いました。
あるディレクトリ以下のファイルを一覧取得してデータを読み込むといったことを行いました。
NSFileManagerには他にもファイル操作に関するメソッドが用意されています。
そこで検索以外の機能を使用してみたいと思います。

ファイルの存在確認

NSFileManagerを使用することでファイルの存在確認が行えるようになっています。
ファイルの存在確認を行うには以下のメソッドを使用します。

- (BOOL) fileExistsAtPath: (NSString*)path
- (BOOL) fileExistsAtPath: (NSString*)path isDirectory: (BOOL*)isDirectory

引数のpathに存在確認したいファイルやディレクトリのパスを指定します。
どちらのメソッドも存在している場合に「YES」が戻り値として返ってくるのですが、上のメソッドでは
存在したのがファイルなのかディレクトリなのかが判定できません。
そういった判定まで行いたい場合は、下のメソッドを使用します。

下のメソッドの場合、第2引数でBOOL型の変数を指定するとその変数の中に、指定したパスがディレクトリであれば「YES」が
そうでないなら「NO」が格納されます。注意するべきところは引数「isDirectory」がポインタになっているところです。
変数をそのまま指定するのではなく、アドレスを渡す必要があります。こういうのを参照渡しといいます。
こうすることでセンダー(メッセージ送信元)側で作成された変数の値を呼び出されたメソッド側で
変更することができます。
呼び出されたメソッド側はアドレスのコピーを保持する形となり、そのアドレス位置の領域を変更すると渡した側の値も
変わるということになります。

逆にアドレスではなく値を渡すことを値渡しといいます。値を渡す場合は、呼び出されたメソッド側はアドレスではなく、
元の変数の値のコピーを保持することになるので、値を変更してもコピーされたものの値が変わるだけで呼び出し元の
変数には変化がありません。

コードで確認

ディレクトリ構成は前回と同様でmain.mと同一ディレクトリ内にdataディレクトリがあり、その中に「data201301.txt」と
「data201302.txt」が配置されています。

まずdataディレクトリがあるかどうかの確認をしたいと思います。
main.mを変更します。
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 *path = @"./data/";
    BOOL isDir = NO;

    Manage *manage = [[Manage alloc] init];
    NSFileManager *filemanager = [ NSFileManager defaultManager];
    //ディレクトリの確認
    if([filemanager fileExistsAtPath:path isDirectory:&isDir]){
        if( isDir == YES ){
            printf("ディレクトリです。n");
        }else{
            printf("ファイルです。n");
            return 1;
        }
    }else{
        printf("ディレクトリが見つかりません。n");
        return 1;
    }
    NSArray *files = [filemanager contentsOfDirectoryAtPath:path error:&error];
    for( i = 0; i < [files count]; i++){
        NSString *filepath = [path stringByAppendingString:[files objectAtIndex:i]];
        printf("file --%s--n",[filepath UTF8String]);
        NSString *file = [NSString stringWithContentsOfFile:filepath
                                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];
        }

    }
    [manage showBestPerson];
    [manage recordBestPerson];
    [manage release];
    [pool drain];
    return 0;
}

前回から変更されてるところをみます。
14行目のところで変数を宣言して初期化しています。この変数をディレクトリかどうかの値の格納に使用します。

19行目のところでpathで指定したものが存在しているかどうかを判定しています。ディレクトリかどうかを判定するため、
引数を2つ使用するほうのメソッドを今回は使用します。
2つ目の引数は上でも述べたようにアドレスを渡さなければなりません。そこで変数の前に「&」をつけています。
ディレクトリであれば「isDir」に「YES」が格納されるはずです。

20行目のところで「isDir」内の値の確認をしています。

21行目以下はディレクトリかどうかによって処理を分けています。ディレクトリでなければ、以下のファイル読み込み処理を
行なってもファイル自体を読み込めないので「return 1」を返して終了しています。

後は前回と特に変わりがありません。ディレクトリであることを確認できたら内部のファイルを読み込んで
ユーザデータを処理しています。

結果確認

結果を確認してみましょう。
まず試しに「data」ディレクトリを別名にしてみると以下のようになります。
Objc25-1

pathの内容のものが存在していないので、「ディレクトリが見つかりません。」となっています。

元に戻すと以下のようになります。
Objc25-3

ディレクトリと判定されていますね。

まとめ

今回のまとめとして
・NSFileManagerクラスのfileExistsAtPathを使用してディレクトリとファイルの存在確認を行うことができる
・以前にもありましたが、メソッドに引数を指定する際に、参照渡しと値渡しがある
・参照渡しはアドレスが渡されるため元の変数の値を操作でき、値渡しは元の値のコピーが渡されるため元の変数は変わらない
といったところでしょうか。

  • このエントリーをはてなブックマークに追加

PAGE TOP