首先,Java中的文本类型包括String/char/Reader/Writer,它们内部都是使用Unicode编码,因此可以组合所有字符集。
这与C/C++等语言的区别很大,后者没有这样的标准。
另外,由于历史原因,System.in被视为InputStream。因此需要指定所使用的编码方式。
Scanner sc = new Scanner(System.in, "Windows-1251");
以上明确将System.in的转换设置为Cyrillic。如果没有这个可选参数,则会采用默认编码。如果该软件没有更改它,那么它将是平台编码。因此这也可能是正确的。
现在,text
已经正确,包含了来自System.in的Unicode字符。
你会得到UTF-8字节:
byte[] bytes = text.getBytes(StandardCharsets.UTF_8)
旧的文本重新编码是错误的,可以去掉这行。事实上,并非所有的Windows-1251字节都是有效的UTF-8多字节序列。
String result = text
System.out.println(result)
System.out是一个PrintStream,是一个相当罕见的历史类。它使用默认平台编码打印输出。在某种程度上,我们可以依赖它来确保默认编码是正确的。
System.out.println(result)
如果要打印到一个UTF-8编码的文件中:
byte[] bytes = ("\uFEFF" + text).getBytes(StandardCharsets.UTF_8)
Path path = Paths.get("C:/Temp/test.txt")
Files.writeAllBytes(path, bytes)
我在这里添加了一个Unicode BOM字符,这样Windows记事本就可以将编码识别为UTF-8。通常情况下应该避免使用BOM。它是一个零宽度空格(=不可见),并且会对各种格式造成麻烦:CSV、XML、文件串联、剪切-复制。