Java char设置编码问题(从UTF8到cp866)

Nik*_*yGS 10 java character-encoding

如何将文本从utf8/cp1251(windows cyrillic)转换为DOS Cyrillic(cp866)

我找到了这个例子:

Charset fromCharset = Charset.forName("utf8");
Charset toCharset = Charset.forName("cp866");

String text1 = "???????"; // my name in bulgarian
String text2 = "Nikolay"; // my name in english

System.out.println("TEXT1 :[" + toCharset.decode(fromCharset.encode(text1)).toString() + "]");
System.out.println("TEXT2 :[" + toCharset.decode(fromCharset.encode(text2)).toString() + "]");
Run Code Online (Sandbox Code Playgroud)

输入是:

TEXT1 :[??????????????] // WRONG
TEXT2 :[Nikolay]  // CORRECT
Run Code Online (Sandbox Code Playgroud)

问题出在哪儿?

Joa*_*uer 13

第一个:如果你有一个String对象,那么它不再有编码,它是一个纯Unicode字符串(*)!

在Java中,编码在您从bytes(byte[])转换为字符串(String)时使用,反之亦然.(理论上你可以直接转换byte[]byte[]但我还没有看到用Java完成的转换).

如果你有一些cp1251编码数据,那么它必须是一个byte[](即一个字节数组)或某种流(例如,作为一个提供给你InputStream).

如果你想提供一些数据为cp866,那么你必须提供它byte[]作为某种流或某种流(例如`OutputStream).

另外:没有"utf8/cp1251"这样的东西.UTF-8和CP-1251是几乎不相关的字符编码.您的输入是UTF-8或CP-1251(或其他).它不可能都是(+).

这里是必须的链接:绝对最低每个软件开发人员绝对必须知道Unicode和字符集(没有借口!)

(*)是的,严格来说它有一个编码,它是UTF-16,但是对于大多数用途你可以(而且应该)把它想象成一个"无编码的理想Unicode字符串"
(+)严格来说它可能是两者都是如果它是只使用在两种编码中编码为相同字节的字符,通常是ASCII子集


Jon*_*eet 5

问题是你试图解码一个编码的输出,就好像它是一个不同的编码.

想象一下,你有一个只能写出JPEG的程序,另一个只能读取PNG的程序...你希望能用第二个程序读取第一个程序的输出吗?

在这种情况下,两种编码恰好兼容ASCII字符,但从根本上说你做错了.

如果您的文本已经是UTF-8,则应该使用UTF-8编码将二进制数据读取为Unicode字符串,然后再使用其他编码其写入二进制数据.Unicode是基本的中间步骤,作为Java的本机文本格式.这相当于将JPEG输出加载到另一个程序中,该程序可以在您使用第二个应用程序读取之前执行转换为PNG.


bas*_*sil 5

简短解决您的问题:

\n\n
 System.out.write("\xd0\x92\xd0\x90\xd0\xa1\xd0\xaf\\n".getBytes("cp866")); // its right\n System.out.println("\xd0\x92\xd0\x90\xd0\xa1\xd0\xaf".getBytes("cp866")); // its wrong\n
Run Code Online (Sandbox Code Playgroud)\n\n

cmd.exe 的结果:

\n\n

C:\\Documents and Settings\\afram\\\xd0\x9c\xd0\xbe\xd0\xb8 \xd0\xb4\xd0\xbe\xd0\xba\xd1\x83\xd0\xbc\xd0\xb5\xd0 \xbd\xd1\x82\xd1\x8b\\NetBeansProjects\\Encoding\\dist>java -jar Encoding.jar

\n\n

\xd0\x92\xd0\x90\xd0\xa1\xd0\xaf

\n\n

[B@1bab50a

\n