【问题标题】:bytes of a string is transformed between creation of the string and getBytes()字符串的字节在创建字符串和 getBytes() 之间转换
【发布时间】:2018-09-05 04:51:53
【问题描述】:

我有一个意外行为,我想知道这是否是预期行为,其背后的原因是什么?我使用字节数组创建了一个新字符串,当我使用相同的编码返回字节数组时,字节数组就不一样了。

byte[] bytes = new byte[24];
new Random().nextBytes(bytes);
assertEquals( // fails
  DatatypeConverter.printHexBinary(bytes), 
  DatatypeConverter.printHexBinary(new String(bytes, UTF_8).getBytes(UTF_8))
);

【问题讨论】:

  • 是的,字符串不同于字节。不要使用字符串来存储字节,这是一个糟糕的主意。

标签: java string encoding character-encoding byte


【解决方案1】:

并非每个随机字节数组都是有效的 UTF-8。事实上,我会说其中很少。因此,在创建字符串时,您会将一些字符转换为 U+FFFD,这表明在确定原始字节时存在错误。当然,这些在转换回字节时看起来会有所不同。

如果您想要干净的往返行程,请不要将无效的数据放入其中。或者您可以使用像 Latin-1 这样的编码,而不是每个字节都是有效的,因此保持不变。但通常将不是文本的随机数据放在字符串中很少有用或好主意。这不是在二进制数据和文本之间没有区别的 C 语言。

【讨论】:

  • 对于一个相当愚蠢的问题,这是一个不错的答案。 “ASCII”编码在这里是否等同于“Latin-1”?
  • 可能不会,因为 127 以上的所有内容都是无效的 ASCII,我猜会被转换为 ?
  • 我认为当一个字符无效时它会失败,但实际上你是对的,它只是用未知字符替换。我使用了 Latin-1 (StandardCharsets.ISO_8859_1),现在它可以工作了。
【解决方案2】:

您正在使用随机生成的字节来创建String。无法保证这些随机生成的字节是有效的 UTF-8(或任何编码)。如果您查看String(byte[],Charset) 的文档,您会看到:

此方法总是用此字符集的默认替换字符串替换格式错误的输入和不可映射的字符序列。

这意味着如果输入的字节无效,则不一定与输出的字节相同;即使使用相同的Charset

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多