Oracle から Java 7 を使用している場合、Mac OS X で非 ASCII 文字を含むファイル名で File.list() を使用すると、正しく取得されないという問題があります。
次の例を使用しています。
import java.io.*;
import java.util.*;
public class ListFiles {
public static void main(String[] args)
{
try {
File folder = new File(".");
String[] listOfFiles = folder.list();
for (int i = 0; i < listOfFiles.length; i++)
{
System.out.println(listOfFiles[i]);
}
Map<String, String> env = System.getenv();
for (String envName : env.keySet()) {
System.out.format("%s=%s%n",
envName,
env.get(envName));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
この例を Apple の Java 6 で実行すると、すべて問題ありません。
....
Folder-ÄÖÜäöüß
吃饭.txt
....
この例を Oracle の Java 7 で実行すると、結果は次のようになります。
....
Folder-A��O��U��a��o��u����
������.txt
....
ただし、環境を次のように設定すると (上記の 2 つのケースでは設定されません):
LANG=en_US.UTF-8
Oracle の Java 7 での結果は期待どおりです。
....
Folder-ÄÖÜäöüß
吃饭.txt
....
私の問題は、LANG 環境変数を設定したくないということです。これは、Mac OS X アプリケーションとしてデプロイしたい GUI アプリケーションであり、そうすることで、LSEnvironment 設定
<key>LSEnvironment</key>
<dict>
<key>LANG</key>
<string>en_US.UTF-8</string>
</dict>
Info.plist では効果がありません (こちらも参照)
LANG 環境を設定せずに Mac OS X 上の Oracle から Java 7 でファイル名を正しく取得するにはどうすればよいですか? Windows および Linux では、この問題は存在しません。
編集:
個々のバイトを次のように印刷すると:
byte[] x = listOfFiles[i].getBytes();
for (int j = 0; j < x.length; j++)
{
System.out.format("%02X",x[j]);
System.out.print(" ");
}
System.out.println();
正しい結果は次のとおりです。
Folder-ÄÖÜäöüß
46 6F 6C 64 65 72 2D 41 CC 88 4F CC 88 55 CC 88 61 CC 88 6F CC
88 75 CC 88 C3 9F
吃饭.txt
E5 90 83 E9 A5 AD 2E 74 78 74
間違った結果は次のとおりです。
Folder-A��O��U��a��o��u����
46 6F 6C 64 65 72 2D 41 EF BF BD EF BF BD 4F EF BF BD EF BF BD
55 EF BF BD EF BF BD 61 EF BF BD EF BF BD 6F EF BF BD EF BF BD
75 EF BF BD EF BF BD EF BF BD EF BF BD
������.txt
EF BF BD EF BF BD EF BF BD EF BF BD EF BF BD EF BF BD 2E 74 78 74
そのため、LANG が設定されていない場合 (Oracle の Java 7 のみ)、Files.list() が一部のバイトを UTF-8 "EF BF BD" = Unicode U+FFFD = 置換文字に置き換えることがわかります。