当从Oracle使用Java 7时,File.list()在Mac OS X上检索不正确的NON-ASCII字符的文件名

前端之家收集整理的这篇文章主要介绍了当从Oracle使用Java 7时,File.list()在Mac OS X上检索不正确的NON-ASCII字符的文件名前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当使用Oracle 7中的Java 7时,在Mac OS X上使用File.list()的文件名与NON-ASCII字符不正确地检索有问题。

我使用以下示例:

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
....

但是,如果我将环境设置如下(未在上述两种情况下设置):

LANG=en_US.UTF-8

来自Oracle的Java 7的结果是如预期的那样:

....
Folder-ÄÖÜäöüß
吃饭.txt
....

我的问题是我不想设置LANG环境变量。它是一个GUI应用程序,我想要部署为Mac OS X应用程序,并且这样做,LSEnvironment设置

<key>LSEnvironment</key>
<dict>
  <key>LANG</key>
  <string>en_US.UTF-8</string>
</dict>

在Info.plist中没有效果(另见here)

在Mac OS X上的Oracle中,如何在Java 7中正确检索文件名称,而无需设置LANG环境?在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(仅适用于Java 7的Java 7),那么Files.list()将使用UTF-8“EF BF BD”= Unicode U FFFD =替换字符替换某些字节。

如果其他一切都失败,请为JVM创建一个设置LC_CTYPE环境变量的包装器,然后启动应用程序。 OS X不在乎plist告诉它运行哪个程序?在shell脚本中创建这个包装很简单:
#!/bin/bash
export LC_CTYPE="UTF-8" # Try other options if this doesn't work
exec java your.program.Here

问题在于Java – 来自Apple或Oracle的任何Java版本 – 从文件系统读取文件名称文件系统上的文件名称基本上是二进制数据,并且必须对其进行解码,以便在Java中将其用作String。 (你可以在我的博客中加read more about this issue)

编码的检测从平台到版本和版本不同,所以这必须是Apple Java 6和Oracle Java 7不同的地方:Java 6正确地检测到系统设置为UTF-8,而Java 7错误

奇怪的是,当我尝试使用以下程序重现问题时,我发现Java 6和Java 7正确地使用UTF-8来解码文件名(它们被正确地打印到终端)。对于其他I / O,Java 6u35使用MacRoman作为默认字符集,而Java 7u7使用UTF-8(由file.encoding系统属性显示)。

import java.io.*;

public class Test {
  public static void main(String[] args) {
    System.setOut(new PrintStream(System.out,true,"UTF-8"));
    System.out.println(System.getProperty("file.encoding"));
    for (File f: new File(".").listFiles) {
      System.out.println(g.getName());
    }
  }
}

当我在OS 10.7上运行区域设置时,我得到这个输出。似乎在我的系统上,Java 6不能正确解释为LC_CTYPE给定的值。据我所知,系统没有自定义,一切设置为英文,所以这应该是默认配置:

LANG=
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

猜你在找的Oracle相关文章