1

我的 Linux 机器上的默认字符集是 US-ASCII。如果我上传带有变音符号的文件,我的编码有问题。

在示例中,我创建了一个名为 standü.png 的文件。如果我做

new String(f.getName().getBytes(Charset.defaultCharset()),"UTF-8");

我的结果是stand?.png。但我想要standü.png(带变音符号)

//Default Charset is US-ASCII
    System.out.println(Charset.defaultCharset());

    String s = "standü.png";

    File f = new File(s);

    String newstr = new String(f.getName().getBytes(Charset.defaultCharset()),"UTF-8");
    System.out.println(newstr);

我的输出是:

US-ASCII
stand?.png
4

3 回答 3

0

我在美国,靠近旧金山,在 Mac 上运行各种 Java 8。当我按原样运行您的代码时,我得到了变音符号:

UTF-8
standü.png

我有点想我会得到这个,因为我从过去的经验中知道我的默认字符集是某种可以保留外来字符的 unicode。为什么您的默认字符集 ASCII 是?这似乎是你的问题。

正如我在评论中所说,我认为您可以将“Charset.defaultCharset()”更改为“Charset.forName(”UTF-8") 来解决您的问题。我不能确定,但​​如果我将其设置为“ Charset.forName("ASCII"),然后我得到你的输出。所以看起来这应该为你解决问题。

所以只需改变:

String newstr = new String(f.getName().getBytes(Charset.defaultCharset()),"UTF-8");

至:

String newstr = new String(f.getName().getBytes(Charset.forName("UTF-8"),"UTF-8");

此外,这不会给你你的变音符号:

String newstr = f.getName();
System.out.println(newstr);

如果我理解正确的话,因为一切都一直保持 unicode。当您必须将名称转换为字节流时,问题就出现了。如果你不必这样做,你会没事的。如果你这样做,那么显式使用 UTF-8 而不是默认字符集,我认为你也会很好。

于 2019-02-27T02:07:22.670 回答
0

如果要在文件系统上创建名称包含非 ASCII 字符的文件,则实际上不需要任何转换。

import java.io.File;
import java.io.IOException;

public class Test {

  public static void main(String[] args) throws IOException {
    new File("ü").createNewFile();
  }
}

这实际上会在我的文件系统上创建一个名为“ü”的文件。请注意,我在 Linux 上,文件名实际上是一个字节序列(在这种情况下,它将是 0xC3 0xBC)。操作系统不会将文件名解释为字符串。然而,像lswill 这样的程序。他们将使用什么来解释序列取决于语言环境。

$ LC_ALL=en_US.UTF-8 ls 
ü
$ LC_ALL=C ls 
''$'\303\274'

还要注意如何确定编码的正确性。当您在控制台上输出某些内容时,那里还有一个编码,如果设置不正确,您可能会得出错误的结论。

于 2019-02-27T02:38:39.967 回答
-1

您需要使用适当的系统属性启动 JVM,file.encoding并将其设置为文件系统中文件名的编码。由于类 UNIX 操作系统上的文件名通常是字节字符串而不是字符串,因此您必须尝试哪个是正确的:(UTF-8可能)或ISO-8859-1(不太可能)。其中之一应该工作。

官方文档中没有列出属性的名称,但是当您列出属性时,您会很容易地看到它的当前值。

该属性可能需要尽早设置,最好是通过-Dfile.encoding=UTF-8命令行选项。

于 2019-02-27T02:10:12.043 回答