在下面的使用OpenJDK
1.6.0_22在Linux中运行的Java程序中,我仅在命令行中列出了作为参数接收的目录的内容。该目录包含文件名称为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_ALL变量设置为en_US.UTF-8,则结果打印良好。但是,如果我将LC_ALL变量设置为POSIX并从命令行以UTF-8形式提供file.encoding和sun.jnu.encoding属性,则会得到垃圾输出,并且cf.exists()返回false。
能否请您解释这种行为。当我在许多网站上阅读时,据说file.encoding足以读取文件名并将其用于操作。在这里,该属性似乎完全无效。
更新1:
如果将file.encoding设置为GBK(中文),将LC_ALL变量设置为en_US.UTF-8,则cf.exists()返回true。只有 ‘?’
出现而不是文件名。给o_O惊喜。
更新2:进行
更多调查,这似乎不是Java问题。看起来Linux上的libc使用语言环境设置来转换文件名编码,而这些设置将导致找不到文件错误/异常。“
file.encoding”用于Java解释文件名的方式。
更新3
现在看起来的问题是Java如何解释文件名。不管文件编码和LC_ALL环境变量的值如何,以下简单的C代码都可以在Linux上运行(我很高兴这证明了此处给出的答案:https :
//unix.stackexchange.com/questions/39175/understanding-unix-file-
名称编码)。但是我仍然不清楚Java如何解释LC_ALL变量。现在研究一下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');
}
}
注意:所以最后我认为我已经确定了。
我不确定这是正确的。但是通过一些代码阅读和测试,这就是我发现的内容,而且我没有更多时间研究它。如果有人有兴趣,他们可以检查一下,并确定这个答案是对还是错-
我会很高兴:)
我使用的参考资料来自OpenJDK的站点上的以下压缩包: 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()
使用setlocale()
libc的方法设置的。环境变量LC_ALL
用于设置的值sun.jnu.encoding
。在命令提示符下使用-Dsun.jnu.encoding
Java选项使用Java 给出的值将被忽略。
呼叫File.exists()
已被编码在文件中jdk/src/share/classes/java/io/File.java
,并且返回为
return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
getBooleanAttributes()
是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
非常重要
我正在尝试为java设置一个PATH环境变量。当我按照下面的方式设置变量值时,在cmd中输入“java”时,它可以很好地工作 但是对于下面的错误,“java”不被识别为内部或外部命令, 我用的是windows 8。你知道为什么上面的变量不起作用吗?
Git 总是在一个 bash shell 中运行,并借助一些 shell 环境变量来决定它的运行方式。 有时候,知道它们是什么以及它们如何让 Git 按照你想要的方式去运行会很有用。 这里不会列出所有的 Git 环境变量,但我们会涉及最有的那部分。 全局行为 像通常的程序一样,Git 的常规行为依赖于环境变量。 GIT_EXEC_PATH 决定 Git 到哪找它的子程序 (像 git-commit
Puppeteer 寻找某些环境变量来帮助其操作。 如果 puppeteer 在环境中没有找到它们,这些变量的小写变体将从 npm 配置 中使用。 HTTP_PROXY, HTTPS_PROXY, NO_PROXY - 定义用于下载和运行 Chromium 的 HTTP 代理设置。 PUPPETEER_SKIP_CHROMIUM_DOWNLOAD - 请勿在安装步骤中下载绑定的 Chromium。
环境变量 vue-element-admin 4.0 之后是基于 vue-cli来进行构建,所以所有的环境变量配置都是基于vue-cli来实现和控制的。 官方文档 .env # 在所有的环境中被载入 .env.[mode] # 只在指定的模式中被载入 一个环境文件只包含环境变量的“键=值”对: FOO=bar VUE_APP_SECRET=secre
一些 Electron 的行为受到环境变量的控制,因为他们的初始化比命令行和应用代码更早. POSIX shells 的例子: $ export ELECTRON_ENABLE_LOGGING=true $ electron Windows 控制台: > set ELECTRON_ENABLE_LOGGING=true > electron ELECTRON_RUN_AS_NODE 类似nod
设置变量,可以不必更改代码的控制应用程序配置和行为。 某些Electron行为由环境变量控制,因为它们比命令行和代码更早地初始化。 POSIX shell示例: 1 $ export ELECTRON_ENABLE_LOGGING=true 2 $ electron Copied! Windows控制台示例: 1 > set ELECTRON_ENABLE_LOGGING=true 2 > ele