2004 年 10 月 15 日

Déjà Vu:ファイル/フォルダ名の NG ワード

Déjà Vu日次/週次/月次のバックアップを自動化するシステム環境設定項目 Déjà Vu ですが、日本語環境で使用している場合、バックアップ元/バックアップ先のファイル/フォルダ名によっては、稀に動作しない場合があることが判明しました。

例えばバックアップ先フォルダの名前を「テスト」とした場合、console.log に

2004-09-27 21:30:18.025 System Preferences[451] *** -[NSCFArray 
addObject:]: attempt to insert nil
などというエラーが出力されるだけで、バックアップは実行されません。ところが「てすと」とした場合は、特に問題なくすんなりとバックアップが実行されるのです。それではカタカナがダメなのかと思いきや、「ぬるぽ」も「ヌルポ」もバックアップ可能だったりします。ここから察するに、どうやら日本語のファイル/フォルダ名のごく一部にだけ「NGワード」が存在するようなのです。

いまのところ、はっきり NG ワードであると確認できたのは「テスト」だけです。とりあえず、「テスト」という名前の(あるいはパスの一部に「テスト」を含む)ファイル/フォルダは使用を避けてくださ���ようお願いします。また、もし「テスト」以外の NG ワードが見つかったら、ご一報くださると幸いです。

なお、この問題は開発元でも把握済みですが、解決策はまだ見いだせていないとのことです。

Posted by E-WA at 2004年10月15日 01:46 | トラックバック (0)
コメント

ひょっとしたら「テント」も駄目じゃないすかね?

ちと糸口を見つけたのですが、考えをまとめる時間ください。

Posted by: shiro at 2004年10月16日 21:30

ビンゴ。「テント」でも attmpt to insert nil が出力されます。

Posted by: E-WA at 2004年10月16日 21:40

ちょいとヤヤコシイのですが...

NSString から fileSystemRepresentation メソッドでバイト列(char string)に変換したパスを、- stringWithFormat: などのフォーマット付きのメソッドで %s を使って読み込んでないか聞いてみてください。

Objective-C のフォーマット文字列の "%s" は、ASCIIの範疇を越える文字が来た場合、DefaultCStringEncoding として扱います。

日本語の場合、DefaultCStringEncoding は MacJapanese という ShiftJIS のヴァリアントですが、ファイルシステムにファイル名として使われるエンコーディングは UTF-8 です。このため、-fileSystemRepresentation で出力したバイト列は UTF-8 でエンコードされてますが、stringWithFormat: のなどで使われる %s は MacJapanese ( ShiftJIS )を期待しており、ここでの齟齬で文字によって破滅的な結果が出ます。
----------------------------------------------------------------------------
悪い例:
NSLog(@"%s", [ PathString fileSystemRepresentation ] );
----------------------------------------------------------------------------
悪い例:
const char * cstring = [ PathString fileSystemRepresentation ];

NSString *newPathString = [ NSString stringWithFormat: @"foo %s", cstring ];
----------------------------------------------------------------------------
良い例
NSLog(@"%@", PathString );
----------------------------------------------------------------------------
良い例(1)
const char * cstring = [ PathString fileSystemRepresentation ];

NSString *newPathString = [ NSString stringWithFormat: @"foo %@", [ [ [ NSString alloc ] initWithData: [ NSData dataWithBytes: cstring length: strlen( cstring ) ] autorelease ] ];
----------------------------------------------------------------------------
良い例(2)
NSString *newPathString = [ NSString stringWithFormat: @"foo %@", PathString ];
----------------------------------------------------------------------------


要するに、いったん出力したバイト列をフォーマット文字列の"%s" を使って NSString に戻すな。戻したい時は NSData でくるんでから initWithData:encoding: で UTF-8 を明示して NSString に戻して、それからフォーマット文字列の%@ を使って埋め込め、という事です。

Posted by: shiro at 2004年10月16日 23:35

ごめん、一個訂正

× Objective-C のフォーマット文字列の "%s" は、ASCIIの範疇を越える文字が来た場合、DefaultCStringEncoding として扱います。
○ Objective-C のフォーマット文字列の "%s" はDefaultCStringEncoding として扱います。

で、どっかに UTF-8 も MacJapanese(ShiftJIS)も、ASCIIの範疇はほぼ互換している事を示唆してくれると助かります。

Posted by: shiro at 2004年10月16日 23:37

ありがとうございます。
訳すのが大変そうだけど開発元に伝えてみます。

Posted by: E-WA at 2004年10月16日 23:59