用Android和oraclejava进行字符串编码

用Android和oraclejava进行字符串编码,java,android,unicode,character-encoding,Java,Android,Unicode,Character Encoding,我有计算字符串的SHA-256散列的代码,并且注意到对于同一个字符串,我从Android和Oracle Java 7获得了不同的散列。我的哈希代码将字符串转换为字节[],使用: byte[] data = stringData.getBytes("UTF-16"); 通过UTF-16编码,我从Oracle Java和Android Java中得到了不同的结果。这是我正在散列的字符串: // Test Code: String toHash = "testdata"; System.out.pr

我有计算字符串的SHA-256散列的代码,并且注意到对于同一个字符串,我从Android和Oracle Java 7获得了不同的散列。我的哈希代码将
字符串
转换为
字节[]
,使用:

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]
在不同的平台上是否存在导致不同结果的endian ness问题?我真的应该如何准备一个字符串以独立于平台的方式进行散列

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

  • UTF-16LE
  • UTF-16BE

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

      根据:

      解码时,UTF-16字符集将字节顺序标记解释为 指示流的字节顺序,但如果 没有字节顺序标记编码时,它使用大端字节 排序并写入大端字节顺序标记。

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

      然后从:

      因此,其中一个或文档中都存在缺陷。两者都必须是Big-Endian,并且写BOM,所以应该没有任何区别


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

      Ahh,很有趣。它看起来确实像Android(至少2.2)正在进行小的endian转换: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,116,0,100,0,97,0,116,97,0]
      @TajMorton
      -1,-2,116,0..
      是小尾端,带有LE BOM。这是安卓的吗?无论如何,它显然与Android文档相矛盾。对不起,我的格式被破坏了,在我准备好之前我不小心发布了。Oracle Java 7给出了带有“UTF-16”的
      [-2,-1,0,116]
      ,而Android 2.2给出了
      [-2,-1,116,0]
      。所以是的,它看起来像是在用一个LE BOM生产LE。
      Charset            Encoder writes
      UTF-16BE           BE, no BOM
      UTF-16LE           LE, no BOM
      UTF-16             BE, with BE BOM