java控制台输出的默认字符编码

Java如何确定用于System.out的编码?

鉴于以下课程:

 import java.io.File; import java.io.PrintWriter; public class Foo { public static void main(String[] args) throws Exception { String s = "xxäñxx"; System.out.println(s); PrintWriter out = new PrintWriter(new File("test.txt"), "UTF-8"); out.println(s); out.close(); } } 

它被保存为UTF-8,并在Windows系统上使用javac -encoding UTF-8 Foo.java进行编译。

之后在git-bash控制台(使用UTF-8字符集)我做:

 $ java Foo xxõ±xx $ java -Dfile.encoding=UTF-8 Foo xx├ñ├▒xx $ cat test.txt xxäñxx $ java Foo | cat xxäñxx $ java -Dfile.encoding=UTF-8 Foo | cat xxäñxx 

这里发生了什么?

显然java会检查它是否连接到一个terminal,并在这种情况下改变它的编码。 有没有办法强制Java简单地输出纯UTF-8?


我也尝试了cmd控制台。 redirectSTDOUT似乎没有任何区别。 如果没有file.encoding参数,它会输出ansi编码,并用参数输出utf8编码。

Solutions Collecting From Web of "java控制台输出的默认字符编码"

我假设您的控制台仍在cmd.exe下运行。 我怀疑你的控制台真的期待UTF-8 – 我期望它是一个真正的OEM DOS编码(例如850或437) 。

Java将使用JVM初始化期间的默认编码集对字节进行编码 。

在我的电脑上复制:

 java Foo 

Java编码为Windows-1252; 控制台解码为IBM850。 结果: Mojibake

 java -Dfile.encoding=UTF-8 Foo 

Java编码为UTF-8; 控制台解码为IBM850。 结果: Mojibake

 cat test.txt 

猫解码文件为UTF-8; 猫编码为IBM850; 控制台解码为IBM850。

 java Foo | cat 

Java编码为Windows-1252; 猫解码为windows-1252; 猫编码为IBM850; 控制台解码为IBM850

 java -Dfile.encoding=UTF-8 Foo | cat 

Java编码为UTF-8; 猫解码为UTF-8; 猫编码为IBM850; 控制台解码为IBM850

这个猫的实现必须使用启发式来确定字符数据是否是UTF-8,然后将数据从UTF-8或ANSI(例如windows-1252)转换为控制台编码(例如IBM850)。

这可以通过以下命令来确认:

 $ java HexDump utf8.txt 78 78 c3 a4 c3 b1 78 78 $ cat utf8.txt xxäñxx $ java HexDump ansi.txt 78 78 e4 f1 78 78 $ cat ansi.txt xxäñxx 

cat命令可以做出这个决定,因为e4 f1不是有效的UTF-8序列。

您可以通过以下方式更正Java输出:

  • 将控制台编码设置为系统ANSI值
  • 使用控制台类型
  • 像猫一样使用一些shiv层

HexDump是一个简单的Java应用程序:

 import java.io.*; class HexDump { public static void main(String[] args) throws IOException { try (InputStream in = new FileInputStream(args[0])) { int r; while((r = in.read()) != -1) { System.out.format("%02x ", 0xFF & r); } System.out.println(); } } }