Objective-C でパスに日本語を含むファイルを開く
普段は JavaScript 版ばかりを使っているので気付かなかったのだが、メニューバーからオープンダイアログを使ってファイルを読み込ませる場合、パスやファイル名に日本語の文字列があると開くことができなかった。また、ファイルの文字コードが UTF-8 以外のものも開くことができなかった。う〜めんどい。
とりあえず下記のようにすればパスに日本語が含まれていてもファイルを開けるようになった。ファイルの文字コードは UTF-8 限定のまま。
// ファイルから文章を読み込む - (IBAction)readFromFile:(id)sender { NSOpenPanel *oPanel = [NSOpenPanel openPanel]; [oPanel beginWithCompletionHandler:^(NSInteger result) { if (result == NSFileHandlingPanelOKButton) { // パスを取得 NSError *err = nil; NSURL *ifPath = [[oPanel URLs] objectAtIndex:0]; // UTF-8 かな? NSString *text = [NSString stringWithContentsOfFile: [[[ifPath absoluteString] substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] encoding:NSUTF8StringEncoding error:&err]; if (err) { _inputTextArea.string = @"UTF-8 形式のファイルしか読み込めないぞ!\n"; } else { _inputTextArea.string = text; //NSLog(@"選択したファイルは '%@' ですか?", ifPath); } } else if (result == NSFileHandlingPanelCancelButton) { //NSLog(@"キャンセルボタンを押しました"); } else { //NSLog(@"エラーかも"); } }]; }
ちょっとネストしていてわかりにくいけれど、
[[[fPath absoluteString] substringFromIndex:7]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
の部分が NSURL
から NSString
に文字列を変更している部分。NSURL
のままだとパーセントエスケープされた文字列なのだ。例えば テスト.txt
だと %E3%83%86%E3%82%B9%E3%83%88.txt
のようになってしまっている。
検索で引掛った Apple の「ファイルシステムプログラミングガイド」に倣って beginWithCompletionHandler:^(NSInteger result)
を使うようにした。Objective-C もかなり改定してるのね。
stringWithContentsOfFile:
のオプション encoding:NSUTF8StringEncoding
を例えば NSShiftJISStringEncoding
にすると、Shift-JIS
のファイルを開ける。場合分けが面倒なので UTF-8
以外のファイルはダメよんってことにした。
ファイルを保存する場合も、日本語のファイル名にするとパーセントエスケープ文字列になってしまうので変更していく。文字コードは UTF-8 で保存できているので、こちらはパスの問題だけ対処すれば良さそう。
読み込みの時と同じようにして日本語ファイル名で保存できるようになった。
// 結果エリアのテキストをファイルに保存する - (IBAction)writeToFile:(id)sender { NSSavePanel *sPanel = [NSSavePanel savePanel]; [sPanel beginWithCompletionHandler:^(NSInteger result) { if(result == NSFileHandlingPanelOKButton) { // パスを取得 NSURL *ofPath = [sPanel URL]; [_resultTextArea.string writeToFile: [[[ofPath absoluteString] substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] atomically:YES encoding:4 error:NULL]; //NSLog(@"保存したファイルは '%@' ですか?", ofPath); } else if (result == NSFileHandlingPanelCancelButton) { //NSLog(@"キャンセルボタンを押しました"); } else { //NSLog(@"エラーかも"); } }]; }
しかしほんとメソッド名が長いわ。