从文件转换 UTF-8 中读取 unicode 行

Reading unicode lines from files conversion UTF-8

我正在读取一个文本中包含 unicode 转义序列的文件,这里是示例:

\u201c@hannah_hartzler: In line for the gate keeper! @nerk97 @ShannonWalkup\u201d\ud83d\ude0d\ud83d\ude0d\ud83d\ude0d\ud83d\ude0d\u2764\u2764\u2764

当我用 BufferedReader 读取它并用 FileWriter 将它写回另一个文件时,文本变成这样:

“@hannah_hartzler: In line for the gate keeper! @nerk97 @ShannonWalkupâ€ðŸ˜ðŸ˜ðŸ˜ðŸ˜â¤â¤â¤

由于 UTF-8 编码,但我想要的是:

“@hannah_hartzler: In line for the gate keeper! @nerk97 @ShannonWalkup”❤❤❤

我的问题是,如何正确读写文本行,以便打印出正确的字符?

我'不'修改文本行,这只是unicode和utf-8之间的转换问题这是我的代码:

FileReader fileReader = new FileReader("tweets.json");
BufferedReader bufferedReader = new BufferedReader(fileReader);
File tmp = new File("out.txt");
FileWriter fileWriter = new FileWriter(tmp);
BufferedWriter bw = new BufferedWriter(fileWriter);
...
String line = bufferedReader.readLine();
bw.write(line);

Unicode 字符 (\u201c) 被编码为 UTF-8 为:

\xE2\x80\x9C

Windows-1252 中看起来像:

“

所以你的问题不是 Java 代码没有生成 UTF-8,因为它是,而是你用来查看文件内容的任何工具都在 [=15] 中读取它=].

如果您使用像 NotePad++ 这样的程序,您可以通过在 Encoding 下拉菜单中选择适当的选项来更改使用的编码。

仅供参考:Windows-1252 / ISO 8859-1 不支持表情符号,因此您不能使用它。

当您通过 new FileReader("tweets.json"); 打开文件时,其内容将使用系统的默认编码进行解释。当你通过new BufferedWriter(fileWriter)打开目标文件时,字符会再次使用系统默认编码进行编码。这可能看起来像文件被原样复制,但不幸的是,事情并没有那么简单。

当文件的实际字符编码与系统的默认编码不匹配时,这种误解可能会使某些字节被归类为无效,这将导致未指定的行为,这些“字符”可能被过滤掉或被替换替换字符,根据目标文件中的真实编码,这可能会导致垃圾甚至无效字符。

作为,第一个字符已被无损复制,但显示不正确,因为无论您使用什么工具打开文件,都会再次将内容误解为Windows-1252.不过其他的一些字符好像是不可逆的损坏了(不过也有可能是复制到本站的结果)…

您可以使用构造函数
new InputStreamReader(new FileInputStream("tweets.json"), StandardCharsets.UTF_8)
new OutputStreamWriter(new FileOutputStream(tmp), StandardCharsets.UTF_8) 来正确解释 UTF-8 文件,或者更好的是,只复制文件不解释其内容:

Files.copy(Paths.get("tweets.json"), Paths.get("out.txt"));

或者,如果您真的想手动执行复制循环

try(FileChannel in =FileChannel.open(Paths.get("tweets.json"),READ);
    FileChannel out=FileChannel.open(Paths.get("out.txt"),WRITE,CREATE,TRUNCATE_EXISTING)){
    long size=in.size(), trans=out.transferFrom(in, 0, size);
    for(long p=trans; p<size && trans>0; p+=trans)
        trans=out.transferFrom(in, p, size-p);
}

(假设你做了 import static java.nio.file.StandardOpenOption.*;

如果以这种方式复制文件,可以确保不会发生损坏。然后你可能会专注于使用一个编辑器,在打开副本时使用正确的编码读取它们。