【问题标题】:Converting String to UTF-8 byte array returns a negative value in Java将字符串转换为 UTF-8 字节数组在 Java 中返回负值
【发布时间】:2017-05-10 08:31:40
【问题描述】:

假设我有一个字节数组,我尝试使用以下代码将其编码为 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,我的字节仍包含负值?我做错了什么吗?有人可以让我澄清这个问题,因为我仍然是这个主题的初学者。谢谢。

【问题讨论】:

  • 这本质上是stackoverflow.com/questions/3621067/…的副本
  • "Encode it to UTF_8" 意味着数据是文本。 “有一个字节数组”意味着它是用一些字符编码编码的。如果是这样,是哪个?或者,正如 Jon Skeet 指出的那样,如果它还不是文本,则应首先使用 Base64 或类似方法将其转换为文本。

标签: java arrays string encoding utf-8


【解决方案1】:

回答具体问题

这是否意味着尽管将其转换为 UTF-8,我的字节仍然包含负值?

是的,当然。那是因为 byte 是用 Java 签名的。 byte 值 -61 将是 195 作为无符号值。当您使用 UTF-8 对任何非 ASCII 文本进行编码时,您应该期望得到不在 0-127 范围内的字节。

修复很简单:只需使用位掩码将范围限定为 0-255:

frequencies[b & 0xff]++;

解决您正在尝试做的事情

这一行:

String tekst = new String(result2, StandardCharsets.UTF_8);

... 仅当 result2 是真正的 UTF-8 编码文本时才适用。如果result2 是一些任意二进制数据,例如图像、压缩数据,甚至是以其他编码方式编码的文本,则合适。

如果要将任意二进制数据保存为字符串,则应使用 Base64 或 hex 之类的内容。基本上,您需要确定您的数据是固有文本(在这种情况下,您应该尽可能多地使用字符串,并在必要时使用适当的Charset 转换为二进制)还是固有二进制(其中如果您应该尽可能多地使用字节,并在必要时使用 base64 或十六进制转换为文本)。

这一行:

byte[] orig = tekst.getBytes();

...几乎总是是个坏主意。它使用平台默认编码将字符串转换为字节。如果您真的非常想使用平台默认编码,我会明确表示:

byte[] orig = tekst.getBytes(Charset.defaultCharset());

...但这是当今非常不寻常的要求。在所有地方都坚持使用 UTF-8 几乎总是更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    相关资源
    最近更新 更多