使用jnlp/webstart在OSX上使用Java 7对文件名进行编码问题

Dur*_*min 11 java macos jnlp character-encoding java-7

我遇到了这个问题,并且已经进行了几天不成功的搜索和解决方法尝试.

我现在有一个由jnlp/webstart在osx和windows计算机上分发的内部java swing程序,除其他外,它从WebDav下载一些文件.

最近,在使用OSX 10.8和Java 7的测试机器上,带有重音字符的文件名和目录名称开始将其替换为问号.

使用7之前的Java版本的OSX没问题.

例如:

XXXYYY_è_ABCD/

XXXYYY _?_ ABCD /

在原始字符串上使用java.text.Normalizer(NFD,NFC,NFKD,NFKC),结果不同但仍然错误:

XXXYYY_e?_ABCD /

要么

XXXYYY_e_ABCD /

我知道,来自oracle.com的[andrew.brygin]和[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=
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

但是我不认为因为webstart而我可以使用这个选项,而且我还没有找到任何方法来从程序中设置LC_CTYPE环境变量.

任何解决方案或解决方法?

PS:

如果我们直接从shell运行程序,它甚至可以在OSX 10 + Java 7上正确写入文件/目录.问题只出现在JNLP + OSX + Java7的组合中

Esa*_*ija 5

我认为文件名的最大ASCII表示是可以接受的,几乎可以在任何编码中使用.

首先,您要特别使用NFKD,以便以ASCII格式保留最大信息.例如,"2?""25"而不仅仅是 "2","?"变得"fi"而不是""等一旦非ASCII和非控制字符被过滤掉.

String str = "XXXYYY_è_ABCD/";
str = Normalizer.normalize(str, Normalizer.Form.NFKD);
str = str.replaceAll( "[^\\x20-\\x7E]", "");
//The file name will be XXXYYY_e_ABCD no matter what system encoding
Run Code Online (Sandbox Code Playgroud)

然后,您将始终通过此过滤器传递文件名以获取其文件系统名称.你只丢失了一些独特性,IE文件asdé.txt是相同的asde.txt,在这个系统中它们是无法区分的.


Dur*_*min 0

我认为目前这个问题还没有真正的解决方案。

与此同时,我得出的结论是,从程序内部打印的“C”环境变量来自 Java Web Start 沙箱,并且(显然是按照设计)您无法影响那些使用 jnlp 的环境变量。

接受的(公司接受的)解决方法/妥协是使用 javaws 从 bash 脚本启动 jnlp。

显然,从浏览器或 finder 启动 jnlp 会创建一个新的沙箱环境,但未设置 LANG(因此设置为等于 ASCII 的“C”)。从命令行启动 jnlp 会从系统默认值打印正确的 LANG,并从 shell 继承它。

这至少允许保留 jnlp 和依赖项的自动更新功能。

不管怎样,我们向 Oracle 发送了一份错误报告,但我个人并不希望它能很快得到解决(如果有的话)。