2009-10-09 10 views
12

ファイルでさまざまなIO操作を行うコードを扱っています。国際的なファイル名を処理できるようにしたいのです。私はJava 1.5でMacで作業しています。ファイル名にサロゲートを必要とするUnicode文字が含まれていると、JVMはそのファイルを見つけることができません。例えば、私のテストファイルがある:Javaの文字\u8349\uD85B\uDFF6\u9DD7\u5916.gifJavaは、ファイル名で代理Unicode値を持つファイルを開くことができませんか?

私はこのファイル名からファイルを作成した場合、私はするFileNotFound例外を取得するので、私はそれを開くことができませんに分かれます

"草鷗外.gif"。でも、失敗したファイルを含むフォルダにこれを使用して:

File[] files = folder.listFiles(); 
for (File file : files) { 
    if (!file.exists()) { 
     System.out.println("Failed to find File"); //Fails on the surrogate filename 
    } 
} 

は、私が実際に取り扱っておりますコードのほとんどの形式は次のとおりです。

FileInputStream instream = new FileInputStream(new File("草鷗外.gif")); 
// operations follow 

は、私はこの問題に対処することができますいくつかの方法があり、ファイル名をエスケープするか、ファイルを別々に開くかのどちらかです。

+0

環境内のCharset.defaultCharset()の値は何ですか? –

+2

(残念なことに、StackOverflowにもサロゲートに問題があり、質問からU + 26FF6表意文字を削除しました) – bobince

+0

System.getProperty( "file.encoding")が返すものを提供できますか?エンコードjava -dfile.encoding = ENCODING_GOES_HEREを変更して、システムのロケールを変更しないようにしてください。これもまた効かなければ、我々は専門家がそれを解決するのを待つでしょう。 – JCasso

答えて

4

環境のデフォルトロケールにこれらの文字が含まれていない場合は、ファイルを開くことができません。

参照:File.exists() fails with unicode characters in name

編集: よし..あなたが必要なもの、システムのロケールを変更することです。どんなOSを使用していても。

編集

参照:How can I open files containing accents in Java?

参照:JFileChooser on Mac cannot see files named by Chinese chars?

+0

システムロケールを変更しないとこれを行うことはできませんか?私が作成しているプログラムは、どのロケールでも実行する必要があり、これらの文字を入力して、これらのファイルをUS/Englishロケールで扱うことができるはずです。 – Bear

+0

不正な解決策 - ユーザーがアプリを実行しているため、自分のコンピュータに座らないためです。また、ロケールが異なっていて、これを行うための管理者がいません。 –

+0

AFAIK他に解決策はありません。この制限はSun/Oracle Javaにあります。ユーザーに保存ダイアログを表示しても問題ない場合は、JFileChooserを試すことができます。 – JCasso

7

私は、JavaやMacの一つではなく、適切なUTF-8のCESU-8を使用している疑いがあります。 Javaはさまざまな内部目的のために "modified UTF-8"(CESU-8のわずかなバリエーション)を使用していますが、ファイルシステム/ defaultCharsetとして使用することはできませんでした。残念ながら、私はここでMacとJavaをテストしていません。

「変更されました」は、「ひどく盗難されました」と言う修正された方法です。代わりのような文字を補足(非BMP)のための4バイトのUTF-8シーケンスを出力する&

\xF0\xA6\xBF\xB6 

それがサロゲートのそれぞれについて、UTF-8でエンコードされたシーケンスを出力#x26FF6 ;::

\xED\xA1\x9B\xED\xBF\xB6 

これは有効なUTF-8シーケンスではありませんが、多くのデコーダがこれを許可します。問題は、実際のUTF-8エンコーダーを使って、上の4バイトの文字列とは異なる文字列を往復することです。その名前のファイルにアクセスしてブームを起こしてみてください!失敗します。

だから、最初のはただのファイル名が実際に、このようなPythonの2.xのようにファイル名のバイトを使用していますプラットフォームを使用して、あなたの現在のファイルシステムの下に格納されているかチェックしてみましょう:私のファイルシステム(Linuxでは、ext4の上で

$ python 
Python 2.x.something (blah blah) 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> os.listdir('.') 

を、UTFを-8)、ファイル名 "草𦿶鷗外。「gif」は次のようになります。

['\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif'] 

それがあなたが得るものなら、それはおそらくJavaが間違っていることでしょう。あなたが長い6バイト文字のバージョンを取得した場合:おそらくOS Xが間違ってそれをやって

['\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif'] 

それはだが...それは常にこのようなファイル名を格納していますか? (またはファイルはもともとどこか別の場所から来たのか?)あなたが「正しい」バージョン?:

os.rename('\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif', '\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif') 
+2

実際には仕様の一部であるため、バグではありません。(よく混乱していても) – finnw

+0

pythonコマンドの結果は最初にリストアップされた適切なファイル名でした。 – Bear

+0

ああ、残念です。壊れたCESU-8の状況が検出されたとしても、それを回避してバイト指向のファイル名インターフェイスを得る方法は考えられません。 :-(あなたがサロゲイトを修正するまでサロゲートを明示的に禁止する必要があるかもしれません。 – bobince

3

にファイルの名前を変更する場合、これは1.5と1.6でテストマックJVMでの問題(であることが判明何)。補助文字/サロゲートペアを含むファイル名には、Java Fileクラスではアクセスできません。私はCarbon版のJNIライブラリをMac版のプロジェクト用に作成しました(ick)。 UTF-8文字を取得するためのJNI呼び出しがCESU-8文字列を返したので、私はCESU-8の問題を疑っています。それはあなたが本当に周りを回ることができるもののように見えません。

0

これはold-skool javaファイルapiのバグです。とにかく、新しいjava.nio APIがうまく動作します。私は、java.io.Fileと関連するクラスを使ってロードできなかったUnicode文字とコンテンツを含むいくつかのファイルを持っています。使用するすべての私のコードを変換した後java.nio.Pathすべてが働き始めました。そして、私は同じ問題を抱えているorg.apache.commons.io.FileUtilsをjava.nio.Files ...

...に置き換え、適切な文字セットを使ってファイルの内容を読み書きしてください。 Files.readAllLines(myPath、StandardCharsets.UTF_8)