java.io.File:访问文件编码无效的文件

时间:2014-04-01 02:32:16

标签: java encoding character-encoding

因为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。文件名应包含ö,ü或ä等字符。

BTW:如果你把编码不适合LC_ALL的文件名放到maven的资源路径中,它就会跳过它....

更新II。

解决此问题:https://github.com/jjYBdx4IL/filenameenc

即。使f.exists()语句变为true。

更新III。

解决方案是使用java.nio。*,在我的情况下,你必须用Files.newDirectoryStream()替换File.listFiles()。我在github上更新了这个例子。 BTW:maven似乎仍然使用旧的java.io API .... mvn clean失败。

4 个答案:

答案 0 :(得分:4)

解决方案是使用新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的一个简单理由!

答案 1 :(得分:0)

目前我坐在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);
}

答案 2 :(得分:-2)

String可以表示任何编码:

new File("the file name with \u00d6")

new File("the file name with Ö")

答案 3 :(得分:-3)

您可以在读取和写入文件时设置编码。例如,当您写入文件时,您可以将编码提供给您的输出流编写器,如下所示。 new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8")

当您读取文件时,您可以将解码字符集作为流动类构造函数。 InputStreamReader(InputStream in, CharsetDecoder dec)