簡體   English   中英

java.nio.file.InvalidPathException:使用國家字符時格式錯誤的輸入或輸入包含不可映射的字符

[英]java.nio.file.InvalidPathException: Malformed input or input contains unmappable characters when using national characters

我正在嘗試創建一些具有國家符號(如“äöü”等)的目錄。不幸的是,每當嘗試這樣做時,我都會遇到此異常:

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),我的export JAVA_OPTS="-Dfile.encoding=UTF-8 ...以: export JAVA_OPTS="-Dfile.encoding=UTF-8 ...

有沒有人有解決這個問題的方法? 我需要能夠在目錄/文件名中使用這些國家符號...

編輯:

在我的 Tomcat 的 setenv.sh 開頭添加額外選項 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();

它似乎失敗 (new FileOutputStream(myOutputFile)); 當它嘗試使用 File 對象初始化 FileOutputStream 時,該對象具有從字符串創建的路徑,該字符串是從上述異常中的路徑中檢索到的,並在末尾添加了文件名。

所以現在創建了目錄,但是在其中寫入或創建任何內容仍然會導致上述異常,盡管其中的文件不包含國家符號。

在沒有國家符號的情況下在其中創建路徑和文件與更改 setenv.sh 之前一樣完美,所以看起來問題仍然與路徑中的國家符號有關......

只需設置環境變量“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)
  1. Java 在此方法中將所有字符串本地轉換為平台的本地編碼: jdk/src/share/native/common/jni_util.c - JNU_GetStringPlatformChars() 。 系統屬性 sun.jnu.encoding 用於確定平台的編碼。

  2. sun.jnu.encoding 的值設置在 jdk/src/solaris/native/java/lang/java_props_md.c - GetJavaProperties() 使用 libc 的 setlocale() 方法。 環境變量 LC_ALL 用於設置 sun.jnu.encoding 的值。 在命令提示符下使用 Java 的 -Dsun.jnu.encoding 選項給出的值將被忽略。

(來自https://stackoverrun.com/cn/q/3020937

如果在您的源中硬編碼了國家字符,請將源文件轉換為相同的編碼。 你可以使用vim:

vim SourceClassWithHardcodedCharacters.java
:set fileencoding=utf-8<Enter>
:w<Enter>

如果出現問題,您將收到一條消息(“不可映射的字符 (...)”)。

對我來說,這個問題與 1. 編碼不正確的硬編碼字符或 2. 在將路徑傳遞給方法的過程中以某種方式丟失編碼有關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM