簡體   English   中英

java.io.File:訪問文件名編碼無效的文件

[英]java.io.File: accessing files with invalid filename encodings

因為 java.io.File 的構造函數將 java.lang.String 作為參數,所以似乎不可能告訴它在訪問文件系統層時期望使用哪種文件名編碼。 因此,當您通常使用 UTF-8 作為文件名編碼並且有一些文件名包含編碼為 ISO-8859-1 的變音符號時,您基本上是** 這個對嗎?

更新:因為似乎沒有人得到它,所以自己嘗試一下:創建新文件時,環境變量 LC_ALL(在 Linux 上)確定文件名的編碼。 你在源代碼中做了什么並不重要!

如果您想給出正確答案,請證明您可以使用正確的 ISO-8859-1 編碼創建一個文件(使用常規 Java 方法),而您的 JVM 假定 LC_ALL=en_US.UTF-8。 文件名應包含像ö、ü 或ä 這樣的字符。

順便說一句:如果您將編碼不適合 LC_ALL 的文件名放入 maven 的資源路徑中,它將跳過它....

更新二。

解決這個問題: https ://github.com/jjYBdx4IL/filenameenc

IE。 使 f.exists() 語句變為真。

更新三。

解決方案是使用 java.nio.*,在我的情況下,您必須將 File.listFiles() 替換為 Files.newDirectoryStream()。 我已經更新了 github 上的示例。 順便說一句:maven 似乎仍在使用舊的 java.io API.... mvn clean 失敗。

解決方案是使用新的 API 和file.encoding 示范:

fge@alustriel:~/tmp/filenameenc$ echo $LC_ALL
en_US.UTF-8
fge@alustriel:~/tmp/filenameenc$ cat Test.java
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Test
{

    public static void main(String[] args)
    {
        final String testString = "a/üöä";
        final Path path = Paths.get(testString);
        final File file = new File(testString);
        System.out.println("Files.exists(): " + Files.exists(path));
        System.out.println("File exists: " + file.exists());
    }
}
fge@alustriel:~/tmp/filenameenc$ install -D /dev/null a/üöä 
fge@alustriel:~/tmp/filenameenc$ java Test
Files.exists(): true
File exists: true
fge@alustriel:~/tmp/filenameenc$ java -Dfile.encoding=iso-8859-1 Test
Files.exists(): false
File exists: true
fge@alustriel:~/tmp/filenameenc$ 

少一個使用File的理由!

目前我坐在一台 Windows 機器上,但假設您可以獲取文件系統編碼:

String encoding = System.getProperty("file.encoding");
String encoding = system.getEnv("LC_ALL");

然后您就可以檢查文件名是否有效。 注意:Windows 可以表示 Unicode 文件名,我自己的 Linux 當然使用 UTF-8。

boolean validEncodingForFileName(String name) {
    try {
        byte[] bytes = name.getBytes(encoding);
        String nameAgain = new String(bytes, encoding);
        return name.equals(nameAgain); // Nothing lost?
    } catch (UnsupportedEncodingException ex) {
        return false; // Maybe true, more a JRE limitation.
    }
}

您可以嘗試 File 是否足夠聰明(我無法測試):

boolean validEncodingForFileName(String name) {
    return new File(name).getCanonicalPath().endsWith(name);
}

我如何修復 java.io.File(在 Solaris 5.11 上):

  • 在 shell/global 中設置 LC_* 環境變量。

    例如。 java -DLC_ALL="en_US.ISO8859-1"不起作用!

  • 確保在系統上安裝了 set locale

為什么要解決它?

Java 內部調用nl_langinfo()來查找 HD 上的路徑編碼,它不會注意到通過 -DVARNAME 設置的“for java”環境變量。

其次,如果語言環境由例如設置,這將回退到 C/ASCII。 LC_ALL 未安裝。

["

您可以在讀取和寫入文件時設置編碼。 例如,當您寫入文件時,您可以將編碼提供給輸出流編寫器,如下所示。 new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8")

當您讀取文件時,您可以將解碼字符集作為流類構造函數。 InputStreamReader(InputStream in, CharsetDecoder dec)

暫無
暫無

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

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