在使用OpenJDK 1.6.0_22的linux下运行的下列Java程序中,我只需在命令行中列出as参数中的目录内容。 该目录包含具有UTF-8文件名的文件(例如印地语,普通话,德语等)。
import java.io.*; class ListDir { public static voID main(String[] args) throws Exception { //System.setProperty("file.enCoding","en_US.UTF-8"); System.out.println(System.getProperty("file.enCoding")); file f = new file(args[0]); for(String c : f.List()) { String absPath = args[0] + "" + c; file cf = new file(args[0] + "/" + c); System.out.println(cf.getabsolutePath() + " --> " + cf.exists()); } } }
如果我将LC_ALLvariables设置为en_US.UTF-8,结果将打印正确。 但是,如果我将LC_ALLvariables设置为POSIX,并从命令行以UTF-8的forms提供file.enCoding和sun.jnu.enCoding属性,则会得到垃圾输出,而cf.exists()将返回false。
你能解释一下这个行为吗? 正如我在这么多网站上看到的,file.enCoding据说足以读取文件名并将其用于 *** 作。 这里看起来这个属性根本没有任何作用。
更新1:如果我将file.enCoding设置为GBK(中文)和LC_ALLvariables为en_US.UTF-8,则cf.exists()返回true。 只有 '?' 出现而不是文件名称。 惊喜o_O。
连字符和撇号字符 – 不同语言的相同ASCII码?
linux上的tchar.h
replace为gettext
locale.setlocale(LC_NUMERIC):如何使它在windows上工作
MFC本地化不适用于windows 7的MUI安装
更新2:更多的调查,它看起来不是Java的问题。 它看起来像linux上的libc使用语言环境设置来翻译文件名编码,这些设置将导致文件找不到错误/exception。 “file.enCoding”是Java如何解释文件名的。
更新3现在看起来问题是Java如何解释文件名。 以下简单的C代码在linux上工作,无论LC_ALL环境variables的文件编码和值如何(我很高兴这certificate了这里给出的答案: https : //unix.stackexchange.com/questions/39175/understanding-unix-file-名称编码 )。 但是我还不清楚Java是如何在LC_ALLvariables上解释的。 现在看OpenJDK的代码。
示例C代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> int main(int argc,char *argv[]) { char *argdir = argv[1]; DIR *dp = opendir(argdir); struct dirent *de; while(de = readdir(dp)) { char *abspath = (char *) malloc(strlen(argdir) + 1 + strlen(de->d_name) + 1); strcpy(abspath,argdir); abspath[strlen(argdir)] = '/'; strcpy(abspath + strlen(argdir) + 1,de->d_name); printf("%d %s ",de->d_type,abspath); file *fp = fopen(abspath,"r"); if (fp) { printf("Success"); } fclose(fp); putchar('n'); } }
如何更改.net Web应用程序中的默认文化设置?
标准函数翻译iso-639代码的语言名称?
如何以独立于区域的方式查找本地组?
gettext-commons找不到资源包
InstallshIEld不显示正确的语言
注意:所以最后我想我已经把它钉死了。 我并不确定这是对的。 但是有了一些代码阅读和测试,这就是我发现的,我没有额外的时间去研究它。 如果有人有兴趣,他们可以检查出来,并告诉这个答案是对的还是错的 – 我会很高兴:)
我使用的参考文献来自OpenJDK网站上的这个tarball: openjdk-6-src-b25-01_may_2012.tar.gz
Java在本地将所有字符串转换为平台的本地编码: jdk/src/share/native/common/jni_util.c - JNU_GetStringPlatformChars() 。 系统属性sun.jnu.enCoding用于确定平台的编码。
sun.jnu.enCoding的值设置为jdk/src/solaris/native/java/lang/java_props_md.c - GetJavaPropertIEs()使用libc的setlocale()方法的jdk/src/solaris/native/java/lang/java_props_md.c - GetJavaPropertIEs() 。 环境变量LC_ALL用于设置sun.jnu.enCoding的值。 在命令提示符处使用-Dsun.jnu.enCoding选项给Java给出的值将被忽略。
调用file.exists()已经被编码在文件jdk/src/share/classes/java/io/file.java ,它返回为
return ((fs.getBooleanAttributes(this) & fileSystem.BA_EXISTS) != 0);
在函数: Java_java_io_UnixfileSystem_getBooleanAttributes0()在jdk/src/share/native/java/io/UnixfileSystem_md.c中本地编码(并跳过通过许多文件进行代码浏览的步骤Java_java_io_UnixfileSystem_getBooleanAttributes0() 。 这里宏WITH_FIELD_PLATFORM_STRING(env,file,IDs.path,path)将路径字符串转换为平台的编码。
所以转换成错误的编码实际上会发送一个错误的C字符串(char数组)到随后调用stat()方法。 它将返回结果该文件无法找到。
LESSON: LC_ALL非常重要
我不知道你在哪里阅读关于file.enCoding 。 我没有看到它与System.getPropertIEs记录的其他标准属性提到。 但从我的实验来看,这个值似乎影响了文件内容的编码,而不是文件名 。 如果file.enCoding是POSIX System.out尤其不会打印非ASCII字符。
另一方面,决定哪个编码适用于文件名的linux方法是当前语言环境设置的LC_CTYPE方面。 我看不出为什么Java应该重写这个。 许多其他平台(特别是windows)总是使用Unicode来表示文件名,而不是字节,因此将文件系统的字节级细节公开给Java应用程序没什么意义。
请参阅java.com上的错误4163515 。 它解释说:
file.enCoding特定于JVM的Sun(现在的Oracle)实现 – 其他人可能不支持它
应被认为是只读的
要更改它,您应该修改JVM运行的环境(这是您使用LC_ALL所做的)
还要注意的是,即使改变你的平台的file.enCoding“起作用”,你也不应该那样做,因为它不会改变Oracle JVM通常使用的默认编码,而只是在一些子系统中。 由于该错误显示了String构造函数使用的字节数组所使用的默认编码不受此设置的影响。
总结以上是内存溢出为你收集整理的file.encoding没有任何效果,LC_ALL环境variables做它全部内容,希望文章能够帮你解决file.encoding没有任何效果,LC_ALL环境variables做它所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)