带有IBM JVM(AIX)的Java UTF-8文件名

带有IBM JVM(AIX)的Java UTF-8文件名,java,utf-8,aix,j9,Java,Utf 8,Aix,J9,我很难理解IBMJVM对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中创建一个代表文件

我很难理解IBMJVM对
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()
,它会坚持将其视为拉丁字符串。例如:

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
因此,我的文件名似乎被视为拉丁文1。我已尝试将系统属性设置为
UTF8
,将系统属性设置为
UTF-8
,但均无效。我的
LANG
LC\u所有设置都是
en\u 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

我找到了答案。我真的想帮你

尝试使用
-Dsun.jnu.encoding=UTF-8
标志集运行您的程序。

请参阅此处以获取有效的AIX区域设置列表 我想你们的出口应该是这样的

  export LC_ALL=EN_US
  export LANG=EN_US

AIX上的
java
是否像在其他Unix上一样从区域设置中提取编码?试着以LANG=en_US.UTF-8 java FileTest的形式运行测试程序,但事实并非如此。我忘了在上面加上那个。但是,UTF-8可能无效或未安装,并且我的
LANG
LC\u所有设置都被忽略,但我对SMIT的不熟悉使这一点难以完全确定。请检查此问题()。另外,Java在打开文件名编码不同于系统区域设置的文件时会出现问题。请确保-当您运行
ls
时-输出是
othér
,对吗?字符串在Java中不是拉丁语,而是UTF-16代码单元的序列。您显示的两个表达式是等效的,但第二个表达式只有在放入
(byte)
强制转换后才能编译,而第一个表达式只有在添加单个
(char)
强制转换后才能编译。它们不是拉丁文1。它们是Unicode代码点@durron597:我想你弄错了,用Unicode代码点的
字符[]
初始化
字符串是正确的。创建一个表示文件名的字符串不是问题。创建准确表示文件名的字符串是个问题。您链接到的前一篇文章讨论了Mac OS文件系统如何始终按规范分解的方式存储文件名。这不是问题,我会被诅咒的。确实如此。我需要对此进行更多的研究,但是是的,我认为
sun.jnu.encoding
系统属性确实会影响行为。我对该属性的解读将表明en_US是ISO-8859-1(又名“拉丁1”)而不是UTF-8。这一情况似乎很重要。EN_US列为UTF8,而EN_US列为ISO8859_1“locale-a”命令的输出会给您什么?您应该看到en_US及其别名en_US.8859_1以及en_US及其别名en_US.UTF-8。两个不同的案例引用两种不同的编码,这似乎很愚蠢,但事实似乎如此。Gah,显然
UTF-8
甚至没有安装。我甚至没想过看一下
locale-a
,谢谢。突然间,事情变得更有意义了。不幸的是,我不是管理员。感谢您指出该文档中的大小写,我没有注意到
en_-US
en_-US
之间确实存在差异。您能否确认,使用
en_-US.UTF-8
的区域设置,JVM的行为是否正常?