【问题标题】:Java UTF-8 filenames with IBM JVM (AIX)使用 IBM JVM (AIX) 的 Java UTF-8 文件名
【发布时间】:2012-10-10 10:55:44
【问题描述】:

我无法理解 IBM JVM 的 java.io.File 实现在 JFS2 文件系统上的 AIX 上处理 UTF-8 的方式。我怀疑我忽略了一个系统属性,但我还没有找到它。

假设我有一个名为othér 的文件(其中é 是U+00E9 或UTF-8 字节0xc3 0xa9)。文件名采用 UTF-8 编码,由 C 程序创建:

char filename[] = { 'o', 't', 'h', 0xc3, 0xa9, 'r', 0 };
open(filename, O_RDWR|O_CREAT, 0666);

如果我在 Java 中创建一个代表文件名的 Unicode 字符串,它将无法打开它。此外,如果我在 Java 中使用 File.listFiles(),它坚持将其视为 Latin1 字符串。例如:

String expectedName = new String(new char[] { 'o', 't', 'h', 0xe9, 'r' });
File expected = new File(expectedName);
if (expected.exists())
    System.out.println(expectedName + " exists");
else
    System.out.println(expectedName + " DOES NOT exist");

for (File child : new File(".").listFiles())
{
    System.out.println(child.getName());
    System.out.print("Chars:");
    for (char c : child.getName().toCharArray())
        System.out.print(" 0x" + Integer.toHexString((int)c));
    System.out.println();
}

这个程序的结果是:

% java -Dfile.encoding=UTF8 FileTest
othér DOES NOT exist
othér
Chars: 0x6f 0x74 0x68 0xc3 0xa9 0x72

所以看来我的文件名被视为 Latin1。我尝试将file.encoding 系统属性设置为UTF8 并将client.encoding.override 系统属性设置为UTF-8 无济于事。我的LANGLC_ALL 设置是en_US.UTF-8

% echo $LANG
en_US.UTF-8
% echo $LC_ALL
en_US.UTF-8

我的系统的“主要语言环境”由 SMIT 配置,是“ISO8859-1”。我真的不知道此设置的全部影响,但我无法更改它。我怀疑如果我可以将其更改为“UTF8 English”,那么可能可以解决问题,但由于 JFS2 以 Unicode 存储文件名,而 Java 在内部以 Unicode 运行,我觉得好像应该有一个更通用的解决方案。

我是否可以设置 J9 的另一个系统属性来强制它使用 UTF-8 文件名,而不管我的 SMIT 设置如何?

AIX 版本是 5.2,Java 版本是 IBM J9 (1.5.0),文件系统是 JFS2:

rs6000% uname -a
AIX rs6000 2 5 000A9B7C4C00
rs6000% java -version
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pap32dev-20091106a (SR11 ))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 AIX ppc-32 j9vmap3223-20091104 (JIT enabled)
J9VM - 20091103_45935_bHdSMr
JIT  - 20091016_1845_r8
GC   - 20091026_AA)
JCL  - 20091106
rs6000% mount|grep /home
         /dev/hd1         /home            jfs2   Jun 27 16:02 rw,log=/dev/hd8 

更新:Java6 上仍然会出现这种情况:

% java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build pap3260sr11-20120806_01(SR11))
IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 AIX ppc-32 jvmap3260sr11-20120801_118201 (JIT enabled, AOT enabled)
J9VM - 20120801_118201
JIT  - r9_20120608_24176ifx1
GC   - 20120516_AA)
JCL  - 20120713_01

【问题讨论】:

  • AIX 上的 java 是否像在其他 Unix 上一样从语言环境中获取编码?尝试以LANG=en_US.UTF-8 java FileTest运行测试程序
  • 它没有。我忘了包括上面那个。 但是,UTF-8 可能无效或未安装,我的 LANGLC_ALL 设置被忽略,但我对 SMIT 不熟悉,因此很难完全确定。
  • 检查这个问题(stackoverflow.com/questions/1545625/…)。 AFAIK 在 Java 中打开文件名编码与系统区域设置不同的文件时存在问题。
  • 只是为了确定——当你运行ls——输出是othér,对吧?

标签: java utf-8 aix j9


【解决方案1】:

我找到了答案。我真的想在这里提供帮助。

This is a blog post about your actual issue. I promise.

尝试在设置-Dsun.jnu.encoding=UTF-8 标志的情况下运行您的程序。

【讨论】:

  • 字符串在 Java 中不是 latin1,它们是 UTF-16 代码单元的序列。您显示的两个表达式是等效的,除了第二个表达式在您输入 (byte) 强制转换之前不会编译,而第一个表达式在您添加单个 (char) 强制转换之前不会编译。
  • 他们不是拉丁语1。它们是 Unicode 代码点。 docs.oracle.com/javase/1.4.2/docs/api/java/lang/…
  • @durron597:我认为你弄错了,用char[] Unicode 代码点初始化String 是正确的。
  • 创建一个应该代表文件名的字符串不是问题。创建一个准确代表文件名的字符串的问题。您链接到的上一篇文章讨论了 Mac OS 文件系统如何将文件名存储为规范分解。这不是这里的问题。
  • 我会被诅咒的。确实如此。我需要对此进行更多研究,但是是的,我认为 sun.jnu.encoding 系统属性确实会影响行为。
【解决方案2】:

请参阅此处http://www.ibm.com/developerworks/java/jdk/aix/118/README.html 以获取有效 AIX 语言环境的列表 我认为你的出口应该是这样的

  export LC_ALL=EN_US
  export LANG=EN_US

【讨论】:

  • 我的阅读表明 en_US 是 ISO-8859-1(又名“Latin 1”)而不是 UTF-8。
  • 这个案子似乎很重要。 EN_US 列为 UTF8,而 en_us 列为 ISO8859_1
  • 命令“locale -a”的输出会给你什么?您应该看到 en_US 及其别名 en_US.8859_1 以及 EN_US 及其别名 EN_US.UTF-8。两种不同的情况引用两种不同的编码似乎很愚蠢,但似乎是这样。
  • 呸,显然UTF-8 甚至没有安装。我什至没有想过要看locale -a,谢谢。突然间,事情变得更有意义了。不幸的是,我不是管理员。感谢您指出该文档中的大小写,我没有注意到en_USEN_US 之间确实存在差异。
  • 您能否确认您的语言环境为en_US.UTF-8 JVM 运行正常?
猜你喜欢
  • 2017-09-05
  • 2016-07-27
  • 1970-01-01
  • 2020-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
相关资源
最近更新 更多