假设我有一个字节数组,我尝试使用以下代码将其编码为UTF_8
String tekst = new String(result2, StandardCharsets.UTF_8);
System.out.println(tekst);
//where result2 is the byte array
然后,我使用getBytes()获取字节,其值为0到128
byte[] orig = tekst.getBytes();
然后,我希望使用ff:
对我的byte [] orig进行频率计数int frequencies = new int[256];
for (byte b: orig){
frequencies[b]++;
}
一切顺利,直到遇到错误陈述
java.lang.ArrayIndexOutOfBoundsException: -61
这是否意味着我的字节仍包含负值,尽管将其转换为UTF-8?我有什么不对劲吗?有人可以告诉我这个原因的清晰度我仍然是这个主题的初学者。谢谢。
答案 0 :(得分:7)
回答具体问题
这是否意味着我的字节仍然包含负值,尽管将其转换为UTF-8?
是的,绝对的。那是因为byte
是用Java签名的。 { - 1}}值为-61将为195作为无符号值。当您使用UTF-8编码任何非ASCII文本时,期望应该获取不在0-127范围内的字节。
修复很简单:只需用位掩码将范围钳位到0-255:
byte
解决您尝试做的事情
这一行:
frequencies[b & 0xff]++;
...仅在String tekst = new String(result2, StandardCharsets.UTF_8);
是真正的UTF-8编码文本时才适用。如果result2
是一些任意二进制数据,例如图像,压缩数据,甚至是用其他编码编码的文本,那么不是合适的。
如果要将任意二进制数据保存为字符串,则应使用Base64或hex之类的内容。基本上,您需要确定您的数据是否本质上是文本的(在这种情况下,您应该尽可能多地使用字符串,并在必要时使用适当的result2
转换为二进制)或固有的二进制(在这种情况下,您应该尽可能多地使用字节,并在必要时使用base64或hex转换为文本。
这一行:
Charset
......几乎总是一个坏主意。它使用platform-default编码将字符串转换为字节。如果你真的,真的想使用平台默认编码,我会明确地说:
byte[] orig = tekst.getBytes();
...但是现在这是非常不寻常的要求。在任何地方坚持使用UTF-8几乎总是更好。