我正在尝试创建一些具有国家符号的目录,例如“äöü”等。不幸的是,无论何时尝试,我都会遇到此异常:
java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters: /home/pi/myFolder/löwen
at sun.nio.fs.UnixPath.encode(UnixPath.java:147)
at sun.nio.fs.UnixPath.<init>(UnixPath.java:71)
at sun.nio.fs.UnixFileSystem.getPath(UnixFileSystem.java:281)
at java.nio.file.Paths.get(Paths.java:84)
at org.someone.something.file.PathManager.createPathIfNecessary(PathManager.java:161)
...
at java.lang.Thread.run(Thread.java:744)
我发现的代码如下所示:
public static void createPathIfNecessary(String directoryPath) throws IOException {
Path path = Paths.get(directoryPath);
// if directory exists?
if (!Files.exists(path)) {
Files.createDirectories(path);
} else if (!Files.isDirectory(path)) {
throw new IOException("The path " + path + " is not a directory as expected!");
}
}
我搜索了可能的解决方案,并且大多数建议将语言环境设置为UTF-8,所以如果我将Linux中的语言环境设置为UTF-8,我想我会修复此问题,但我发现它已经是UTF -8所有的时间,尽管新设置它,我仍然遇到同样的问题。
$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
我在Windows 7上没遇到这个问题,它完美地创建了目录,所以我想知道我是否需要改进java代码来更好地处理这种情况,或者在我的Linux中改变一些东西。
我正在运行的Linux是Raspberry Pi 2上的Raspbian:
$ cat /etc/*-release
PRETTY_NAME="Raspbian GNU/Linux 7 (wheezy)"
NAME="Raspbian GNU/Linux"
VERSION_ID="7"
VERSION="7 (wheezy)"
ID=raspbian
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
我在Tomcat 7服务器上运行我的应用程序(我相信Java版本是1.8),我的setenv.sh以:export JAVA_OPTS="-Dfile.encoding=UTF-8 ...
有没有人能解决这个问题?我需要能够在目录/文件名中使用这些国家符号......
修改
在我的setenv.sh开头为Tomcat添加额外选项Dsun.jnu.encoding = UTF-8并重新启动更改后的内容。
目前我的setenv.sh开头看起来像这样
export JAVA_OPTS="-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8
似乎这个例外已经消失,并且创建了带有国家符号的文件夹,但问题似乎无法完全解决,每当我尝试创建/写入该目录中的文件时,我现在得到:
java.io.FileNotFoundException: /home/pi/myFolder/löwen/Lowen.tmp (No such file or directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:206)
at java.io.FileOutputStream.<init>(FileOutputStream.java:156)
at org.someone.something.MyFileWriter.downloadFiles(MyFileWriter.java:364)
...
at java.lang.Thread.run(Thread.java:744)
它发生的代码如下所示:
// output here
File myOutputFile = new File(filePath);
FileOutputStream out = (new FileOutputStream(myOutputFile));
out.write(bytes);
out.close();
似乎失败了(新的FileOutputStream(myOutputFile));当它尝试使用File对象初始化FileOutputStream时,该对象具有从字符串创建的路径,该字符串是从上面的异常中的路径检索的,并且在末尾添加了文件名。
所以现在创建了目录,但是在其中写入或创建任何内容仍会导致上面的异常,尽管其中的文件不包含国家符号。
当没有国家符号时,在它们中创建路径和文件的效果与setenv.sh中更改之前的完美一样,所以看起来问题是连接到路径中的国家符号...
答案 0 :(得分:0)
如果源中的国家字符是硬编码的,请将源文件转换为相同的编码。你可以使用vim:
vim SourceClassWithHardcodedCharacters.java
:set fileencoding=utf-8<Enter>
:w<Enter>
如果出现问题,您将收到一条消息(“不可映射的字符(...)”)。
对我来说,问题与1.编码错误的硬编码字符或2.在将路径传递给方法时以某种方式丢失编码有关。
答案 1 :(得分:0)
只需设置环境变量“ LANG = en_US.UTF-8”或其他一些“ xxx.UTF-8”。(https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html)
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,
jobject file)
{
jboolean rv = JNI_FALSE;
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
if (mkdir(path, 0777) == 0) {
rv = JNI_TRUE;
}
} END_PLATFORM_STRING(env, path);
return rv;
}
#define WITH_PLATFORM_STRING(env, strexp, var)
if (1) {
const char *var;
jstring _##var##str = (strexp);
if (_##var##str == NULL) {
JNU_ThrowNullPointerException((env), NULL);
goto _##var##end;
}
var = JNU_GetStringPlatformChars((env), _##var##str, NULL);
if (var == NULL) goto _##var##end;
#define WITH_FIELD_PLATFORM_STRING(env, object, id, var)
WITH_PLATFORM_STRING(env,
((object == NULL)
? NULL
: (*(env))->GetObjectField((env), (object), (id))),
var)
Java通过以下方法将所有字符串本地转换为平台的本地编码:jdk / src / share / native / common / jni_util.c-JNU_GetStringPlatformChars()。系统属性sun.jnu.encoding用于确定平台的编码。
sun.jnu.encoding的值使用libc的setlocale()方法在jdk / src / solaris / native / java / lang / java_props_md.c-GetJavaProperties()中设置。环境变量LC_ALL用于设置sun.jnu.encoding的值。在命令提示符处使用Java的-Dsun.jnu.encoding选项给出的值将被忽略。