Scanner sc = new Scanner(System.in);
System.out.println("Enter text: ");
String text = sc.nextLine();
try {
String result = new String(text.getBytes("windows-1251"), Charset.forName("UTF-8"));
System.out.println(result);
} catch (UnsupportedEncodingException e) {
System.out.println(e);
}
我正在尝试更改键盘:输入西里尔文键盘,输出拉丁文。示例:qwerty +> йцукен
它不起作用,谁能告诉我我做错了什么?
最佳答案
首先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、文件连接、剪切-复制-粘贴。
关于java将字符串windows-1251转换为utf8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26995472/