在C#与Java中将字符串转换为字节时,我遇到了不同的结果。
C#:
byte[] byteArray = Encoding.Unicode.GetBytes ("chess ¾");
for (int i = 0; i < byteArray.Length; i++)
System.Diagnostics.Debug.Write (" " + byteArray[i]);
System.Diagnostics.Debug.WriteLine("");
System.Diagnostics.Debug.WriteLine(Encoding.Unicode.GetString(byteArray));
显示:
99 0 104 0 101 0 115 0 115 0 32 0 190 0
chess ¾
爪哇:
byte[] byteArray = "chess ¾".getBytes("UTF-16LE");
for (int i = 0; i < byteArray.length; i++)
System.out.print(" " + (byteArray[i]<0?(-byteArray[i]+128):byteArray[i]));
System.out.println("");
System.out.println(new String(byteAppName,"UTF-16LE"));
显示:
99 0 104 0 101 0 115 0 115 0 32 0 194 0
chess ¾
请注意,字节数组中的倒数第二个值是不同的!我的目标是加密这些数据,并能够从C#或Java中读取它。这种差异似乎是一个障碍。
作为旁注,在我学会使用Unicode(C#)/ UTF-16LE(Java)之前,我使用的是UTF-8 ......
C#: byte[] byteArray = Encoding.UTF8.GetBytes ("chess ¾");
显示: 99 104 101 115 115 32 194 190
Java: byteArray = appName.getBytes("UTF-8");
显示: 99 104 101 115 115 32 190 194
其中,奇怪的是导致倒数第二个到最后一个和最后一个字节。
最后,¾
的Unicode是十进制190(http://www.fileformat.info/info/unicode/char/BE/index.htm),而不是十进制194(Â)(http://www.fileformat.info/info/unicode/char/00c2/index.htm)。
非常感谢任何帮助。
答案 0 :(得分:4)
你的问题不在于编码,它是你打印结果的方式,你是使用string
从字节转换为整数,这会给你不正确的结果,使用其他像{ {1}}而是。使用此poc比较两次转化:
byteArray[i] < 0 ? (-byteArray[i] + 128) : byteArray[i]
答案 1 :(得分:1)
我的猜测。
UTF-16LE表示字符占用2或4个字节。
检查this并向下滚动到3/4。您将看到190和194(11000010 10111110) - 这些是编码符号所需的两个字节,显然称为“VULGAR FRACTION THREE QUARTERS”。
创建byte[]
时,数组只能存储1个字节,而不能存储2个字节,因此您将错过一个字节。看起来在C#中你错过了194,在Java中你错过了190。
原因是字节序。请参阅this回答。
在Java中,getBytes(“UTF-16”)返回一个big-endian表示。
C#的System.Text.Encoding.Unicode.GetBytes返回一个小端表示。
但是,在Java中,getBytes("UTF-16LE")
根据this以little-endian返回,这就是你正在使用的。
我现在有疑虑。
我需要更多地思考你在Java中究竟做了什么。还不确定如何解决它。