【问题标题】:String character encoding with Android and Oracle Java使用 Android 和 Oracle Java 进行字符串字符编码
【发布时间】:2012-12-05 06:58:10
【问题描述】:

我有计算字符串的 SHA-256 哈希值的代码,并注意到我从 Android 和 Oracle Java 7 获得了相同字符串的不同哈希值。我的散列码将String 转换为byte[],其中:

byte[] data = stringData.getBytes("UTF-16");

使用 UTF-16 编码,我从 Oracle Java 和 Android Java 得到不同的结果。这是我正在散列的字符串:

// Test Code:
String toHash = "testdata";
System.out.println("Hash: " +DataHash.getHashString(toHash));

并使用 UTF-16 获取这些哈希:

Hash: a1112a0363a59097a701e38398e1fdfef3049358aee81b77ecaad2924a426bc5 [Oracle Java 7]
Hash: 811b723aee07c7a52456fc57a5683e73649075a373d341f7257bf73575111ba3 [Android 2.2]

但是,使用 UTF-8,我得到的两个 JRE 的哈希值相同:

Hash: 810ff2fb242a5dee4220f2cb0e6a519891fb67f2f828a6cab4ef8894633b1f50 [Oracle Java 7]
Hash: 810ff2fb242a5dee4220f2cb0e6a519891fb67f2f828a6cab4ef8894633b1f50 [Android 2.2]

是否存在某种字节序问题导致不同平台上的结果不同?我应该如何真正准备一个字符串以独立于平台的方式进行散列?

编辑: 哎呀,一旦你多读了一点 UTF-16,答案就很明显了。 UTF-16 有两个版本(大端和小端)。您只需要指定 getBytes() 应该使用哪个版本,并且哈希值是相同的。选择以下之一:

  • UTF-16LE
  • UTF-16BE

【问题讨论】:

    标签: java android unicode character-encoding


    【解决方案1】:

    根据documentation of Orcale Java

    解码时,UTF-16 字符集将字节顺序标记解释为 指示流的字节顺序,但默认为 big-endian if 没有字节顺序标记; 编码时使用大端字节 order 并写入 big-endian 字节顺序标记。

    这意味着普通的 UTF-16 在 Oracle Java 中应该始终编码为 Big Endian。

    然后来自Android Java documentation

    Charset            Encoder writes
    UTF-16BE           BE, no BOM
    UTF-16LE           LE, no BOM
    UTF-16             BE, with BE BOM
    

    因此,其中一个或文档中都存在错误。两者都必须是Big Endian,并且写BOM,所以应该没有什么区别。

    一般而言,您应该更喜欢UTF-16BE/LE 而不是UTF-16,但在这种情况下,这似乎是一个错误。

    【讨论】:

    • 啊,有趣。看起来 Android(至少 2.2)正在进行小端转换:Oracle Java 7:UTF-16: [-2, -1, 0, 116, 0, 101, 0, 115, 0, 116, 0, 100, 0, 97, 0, 116, 0, 97]Android Java 2.2:UTF-16: [-1, -2, 116, 0, 101, 0, 115, 0, 116, 0, 100, 0, 97, 0, 116, 0, 97, 0]
    • @TajMorton -1, -2, 116, 0.. 是具有 LE BOM 的 Little Endian。是安卓的吗?无论如何,它显然与 Android 文档相矛盾。
    • 抱歉,我的格式被破坏了,我在准备好之前不小心发布了。 Oracle Java 7 给了[-2, -1, 0, 116] 带有“UTF-16”,而 Android 2.2 给了[-2, -1, 116, 0]。所以是的,它看起来确实是用 LE BOM 生成 LE。
    【解决方案2】:

    显示您的哈希码,但它可能做错了什么。散列的结果是byte[],所以首先不需要从字符串转换为byte[]。要将二进制哈希值转换为String,请使用 Base64 或十六进制编码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      相关资源
      最近更新 更多