我遇到了一个问题,经过几天的不成功搜索和尝试解决方法。我们现在有一个内部Java Swing程序,通过jnlp / webstart分发给OSX和Windows计算机,在下载一些来自WebDav的文件等操作时出现问题。 最近,在具有OSX 10.8和Java 7的测试机器上,带有重音字符的文件名和目录名开始被替换为问号。
在先前版本的Java之前,OSX上没有这个问题。
例如:
XXXYYY_è_ABCD/
变成
XXXYYY_?_ABCD/
在原始字符串上使用java.text.Normalizer(NFD、NFC、NFKD、NFKC)会得到不同但仍然错误的结果:
XXXYYY_e?_ABCD/
或
XXXYYY_e_ABCD/
我从[andrew.brygin at oracle.com]和[mik3hall at gmail.com]之间的信件中获知:
是的,file.encoding是基于jvm运行的语言环境设置的,如果你在xxxx.UTF-8 编码环境下运行你的java vm,那么file.encoding就应该是UTF-8, 如果设成MacRoman将会有问题。所以我认为Oracle/OpenJDK7的表现是正确的。话虽如此,正如Andrew Thompson所指出的,如果所有以前的Apple JDK版本都使用MacRoman作为英语/UTF-8语言环境的file.encoding,那么这里就存在一个“兼容性”问题,可能值得在发行说明中提醒Oracle / OpenJDK MacOS用户。
从Joni Salonen的博客(java-and-file-names-with-invalid-characters)中我了解到:
你可能知道Java使用“默认字符编码”将二进制数据转换为字符串。您可以使用InputStreamReader或OutputStreamWriter来读取或写入另一种编码的文本。但是,在API深处进行数据到文本转换时,您别无选择,只能更改默认编码。
还有
file.encoding怎么样?
file.encoding系统属性也可用于设置Java用于I/O的默认字符编码。不幸的是,它似乎对将文件名解码为字符串的方式没有影响。
在jnlp内部执行locale命令,总是会打印:
LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=
与此类似的stackoverflow问题及其解决方案如下:
encoding-issues-on-java-7-file-names-in-os-x但是解决方案是使用脚本包装Java程序的执行。
#!/bin/bash
export LC_CTYPE="UTF-8" # Try other options if this doesn't work
exec java your.program.Here
但我认为这个选项对我不可用,因为webstart的原因,而且我还没有找到任何方法从程序内部设置LC_CTYPE环境变量。
有什么解决方案或变通方法吗?
P.S. :
如果我们直接从Shell运行程序,则即使在OSX 10+Java 7上它也可以正确地写入文件/目录。问题仅出现在JNLP+OSX+Java7的组合中。