java将字符串windows-1251转换为utf8

hal*_*lem 4 java string character-encoding

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);
    }
Run Code Online (Sandbox Code Playgroud)

我正在尝试更改键盘:输入 cyrylic 键盘,输出拉丁语。示例:qwerty +> ??????

它不起作用,谁能告诉我我做错了什么?

Joo*_*gen 6

首先是java文本,String/char/Reader/Writer内部是Unicode,所以可以组合所有的脚本。这是与没有这样标准的例如 C/C++ 的主要区别。

由于历史原因,现在 System.in 是 InputStream。这需要指示使用的编码。

Scanner sc = new Scanner(System.in, "Windows-1251");
Run Code Online (Sandbox Code Playgroud)

上面明确地将 System.in 的转换设置为 Cyrillic。如果没有此可选参数,则采用默认编码。如果软件没有改变,那就是平台编码。所以这也可能是正确的。

现在text是正确的,包含来自 System.in 的 Cyrillic 作为 Unicode。

您将获得 UTF-8 字节为:

byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

旧的文本“重新编码”是错误的;放下这条线。事实上,并非所有 Windows-1251 字节都是有效的 UTF-8 多字节序列。

String result = text;

System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

System.out 是一个 PrintStream,一个很少使用的历史类。它使用默认平台编码进行打印。或多或少依赖它,默认编码是正确的。

System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

要打印到 UTF-8 编码的文件:

byte[] bytes = ("\uFEFF" + text).getBytes(StandardCharsets.UTF_8);
Path path = Paths.get("C:/Temp/test.txt");
Files.writeAllBytes(path, bytes);
Run Code Online (Sandbox Code Playgroud)

这里我在前面加了一个Unicode BOM字符,所以Windows记事本可能会识别编码为UTF-8。一般来说,应该避免使用 BOM。它是一个零宽度空间(=不可见)并且对各种格式造成严重破坏:CSV、XML、文件连接、剪切复制粘贴。