Java将字符串从windows-1251转换为utf8

6
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 +> йцукен。

但它没有起作用,有人能告诉我我做错了什么吗?


2
你最初想要做什么并不清楚。这种类型的转换几乎总是错误的... - Jon Skeet
这篇文章可以帮助你:http://stackoverflow.com/questions/2288490/how-can-i-convert-a-cp1251-byte-array-to-a-utf8-string - Semih Eker
你最初想要做什么并不清楚。这种转换几乎总是错误的。 我试图更改键盘:输入西里尔字母键盘,输出拉丁字母。例如:QWerty +> ЙЦукен。 - halem
2个回答

6

首先,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、文件串联、剪切-复制。


1
你之所以得到了与自己问题不同的答案且没有人回答你,是因为你的标题不符合问题。你试图转换的并不是字符集,而是键盘布局。
在这里你不需要担心字符布局,只需读取该行,将其转换为字符数组,遍历它们,使用预定义映射进行转换。
代码大致如下:
Map<char, char> table = new TreeMap<char, char>();
table.put('q', 'й');
table.put('Q', 'Й');
table.put('w', 'ц');
// .... etc

String text = sc.nextLine();
char[] cArr = text.toCharArray();
for(int i=0; i<cArr.length; ++i)
{
  if(table.containsKey(cArr[i]))
  {
    cArr[i] = table.get(cArr[i]);
  }
}
text = new String(cArr);
System.out.println(text);

现在,我没有时间测试那段代码,但你应该能够理解如何完成你的任务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接