这里发生了什么?为什么当我使用utf-8读取文件时,它会在控制台中输出问号?
这是一个最小的工作示例:
x1c 0d1x的数据
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeStringToFile;
public class Main {
public static void main(String... args) throws IOException {
System.out.println("---------");
System.out.println(Charset.defaultCharset());
System.out.println("æ ø å");
System.out.println("æ ø å");
System.out.println("æ ø å");
File inputFile = new File(System.getProperty("user.dir") + "/input.md");
File outputFile = new File(System.getProperty("user.dir") + "/output.md");
String content, encoding;
System.out.println("--------- windows-1252");
encoding = "windows-1252";
content = readFileToString(inputFile, encoding);
System.out.println(content);
System.out.println("--------- iso-8859-1");
encoding = "iso-8859-1";
content = readFileToString(inputFile, encoding);
System.out.println(content);
System.out.println("--------- utf-8");
encoding = "utf-8";
content = readFileToString(inputFile, encoding);
System.out.println(content);
writeStringToFile(outputFile, content, encoding);
}
}
字符串
其中input.md
包含:(以UTF-8编码)
This is input.md. 'æ' 'ø' 'å'
型
运行上面的代码会产生
---------
windows-1252
æ ø å
æ ø å
æ ø å
--------- windows-1252
This is file C. 'æ' 'ø' 'å'.
--------- iso-8859-1
This is file C. 'æ' 'ø' 'å'.
--------- utf-8
This is file C. '�' '�' '�'.
型
为什么当我用UTF-8读取文件时会得到�
?这特别奇怪,因为文件是用UTF-8编码的。
UPDATE:我的控制台设置为UTF-8:
的
下面是从输入文件中提取的字符串中每个字符的十六进制值的屏幕截图:
型
下面是一个更好的隔离十六进制的屏幕截图:
的
3条答案
按热度按时间yhuiod9q1#
代码看起来没问题,
output.md
文件看起来也没问题。所以这很可能只是控制台输出的问题。您正在试验的Unicode字符在Windows-1252和ISO-8859-1中编码为相同的单个字节(
æ = 0xE6
,ø = 0xF8
,å = 0xE5
),但在UTF-8中编码为多个字节(æ = 0xC3 0xA6
,ø = 0xC3 0xB8
,å = 0xC3 0xA5
)。阅读一个UTF-8编码的文件,无论是Windows-1252还是ISO-8859-1,都会单独解码每个字节,产生一个
string
,每个字节包含一个单独的char
,而这些char
将具有与字节相同的数值。所以,你应该得到一个string
,包含0x00C3 0x00A6
,0x00C3 0x00B8
,和0x00C3 0x00A5
。将这些char
输出到控制台作为Windows-1252 * 应该 * 显示为æ ø Ã¥
,而不是æ ø å
。另一方面,阅读UTF-8编码的文件作为UTF-8将正确解码文件,生成
string
,其中包含char
、0x00E6
、0x00F8
和0x00E5
。将string
写入UTF-8编码的文件应生成正确的字节序列(0xC3 0xA6
、0xC3 0xB8
和0xC3 0xA5
),但输出与Windows-1252相同的string
会有数据丢失的风险,但您 * 应该 * 会看到预期的æ ø å
,因为Windows-1252确实支持这些Unicode字符。所以,你的结果实际上是从我所期望的倒退。即使
Charset.defaultCharset()
报告的是Windows-1252,我怀疑你的控制台实际上是使用不同的字符集为它的输出。我建议你打印出
content
字符串中每个char
的数值,看看input.md
实际上是如何被每种编码解码的。你应该得到我上面提到的char
值。jckbn6z72#
对于有类似问题的人来说,问题在于控制台的编码(正如@雷米勒博也指出的那样)。
我通过遵循此answer解决了此问题
事实上,我在评论中关注了@Nicolas的回答,并提到了回答:
这也可以从帮助>编辑自定义VM选项.然后重新启动IntelliJ.我真的尝试了一切:在IntelliJ中更改编码设置,更改属性文件设置的JVM选项,build.gradle文件,IntelliJ,运行配置,环境变量等。还尝试更改系统范围的编码,但没有任何效果,除了这个
现在我得到了预期的输出:
x1c 0d1x的数据
piv4azn73#
我遇到了一个类似的问题,我发现我的系统上的 * 一些 * JDK产生了
Cp1252
的file.encoding
,而不是UTF-8。我不知道为什么。然后,您可以添加
-Dfile.encoding=UTF-8
,或者如果您使用Gradle,则可以将org.gradle.jvmargs=-Dfile.encoding=UTF-8
添加到~/.gradle/gradle.properties
(%userprofile%\.gradle\gradle.properties
)或在项目级别添加到gradle.properties
。或者尝试使用所需的
file.encoding
重新安装JDK。