ページ

2009年1月30日金曜日

ファイル名変更(その1)ファイル作成日時でソート

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

tori さんから、キャプチャ画像のファイル名の変更ができないかとの要望が来た。確かに名前が付けられると管理しやすいので便利だ。対応することにした。

ただしファイル名変更にあたっては、SimpleViewerのファイルリストの仕組みに手を入れなければならない。現在はファイル名でソートして、それを順番に SimpleViewerで見られるようにしている。SimpleCapでは SCAP-YYMMDD-nn という決まったファイル名なので、名前のソート=日付順だった。管理するには日付順が便利なのでそうしている。ところがファイル名が自由に付けられるとなると、単純な名前のソートではダメで、ちゃんとファイルの属性情報にあるファイル作成日時を見る必要がある。

そんなこともあるので、まずは SimpleViewerの(内部的な)ファイルリスト作成部分に手をいれる。フォルダ内にあるファイルを取得し、作成日時順で並び替えるようなメソッドなり関数があれば良いのだが、見当たらなかったので作ることにした。

フォルダ内のファイル一覧は NSFileManager#enumeratorAtPath: が使える。他にも contentsOfDirectoryAtPath:error: など簡易なメソッドが用意されているのだが、これらは取得できるのがファイル名だけなので今回は役不足だった。NSFileManager#enumeratorAtPath:NSDicrectoryEnumerator が取得でき、そこから #fileAttributes メソッドでファイルの属性情報(NSDictionary)を取り出すことができる。この属性情報にファイルの作成日時 NSFileCreationDate があり、これが使える。

さて実装だが、ファイルの一覧を扱うクラス FileList と、1ファイルを扱うクラス FileEntry の2つを用意した。

こんな感じ。
FileSet.h

@class FileEntry;
@interface FileList : NSObject {
NSMutableArray* _list;
}

-(void)setPath:(NSString*)path;
- (int)count;
- (int)indexWithFilename:(NSString*)filename;
- (FileEntry*)fileEntryAtIndex:(int)index;
@end


FileEntry.h
@interface FileEntry : NSObject
{
NSString* _name;
NSDate* _created;
}
@property (retain) NSString* name;
@property (retain) NSDate* created;
- (id)initWithFilename:(NSString*)filename fileAttributes:(NSDictionary*)attrs;
@end


FileEntryはプロパティ値として、ファイル名と作成日時を持つ。FileList はこの FileEntryの集まりを配列(NSMutableArray)で保持する。

ファイルリストの生成は #setPath: で行う。
FileList.m
-(void)setPath:(NSString*)path
{
[_list removeAllObjects]; // **clear**

NSFileManager* fm = [NSFileManager defaultManager];
NSDirectoryEnumerator* dir_enum = [fm enumeratorAtPath:path];
FileEntry* entry;

NSString* filename;
NSDictionary* attrs;
while (filename = [dir_enum nextObject]) {
if ([self isTargetFilename:filename]) {
attrs = [dir_enum fileAttributes];
if ([[attrs objectForKey:NSFileType] isEqualToString:NSFileTypeRegular]) {
entry = [[[FileEntry alloc] initWithFilename:filename
fileAttributes:attrs] autorelease];
[_list addObject:entry];
}
}
}
[_list sortUsingSelector:@selector(compare:)];
}


FileManager#enumeratorAtPath: を使い、指定したフォルダ内のファイルを一つ一つ取り出して FileEntryインスタンスへ格納する。#enumeratorAtPath: には画像以外のファイルや、フォルダ内のサブフォルダも含まれる場合も想定して対象となるファイルかどうかのチェックを入れている。現状は、通常のファイルでかつ拡張子が .jpg .gif .png のみ対象としている。最後の #sortUsingSelector: でファイルの作成日時昇順のソートをかけている。ここで使う compare: は FileEntry.m で実装している。

FileEntry.m
- (NSComparisonResult)compare:(FileEntry*)entry
{
return [_created compare:entry.created]; // ASC
// return [entry.created compare:_created]; // DESC
}

元々 NSDate が compare: を実装しているので、それを呼び出すだけ。

これで指定フォルダ内のファイル一覧を作成日時順で取り出すことができた。


なおキャプチャ画像の初期ファイル名は SCAP- を取り除いて元の形に戻した。
(例)090131-0001.png

名前に頼らずフォルダ内のファイルをチェックするようになったので。

- - - -
次は、名前変更のインターフェイスだな。