【问题标题】:Comparison of byte arrays字节数组的比较
【发布时间】:2010-12-08 19:23:17
【问题描述】:

我尝试比较 2 字节数组。

字节数组 1 是一个带有 sha1 哈希的最后 3 个字节的数组:

  private static byte[] sha1SsidGetBytes(byte[] sha1)
  {
    return new byte[] {sha1[17], sha1[18], sha1[19]};
  }

字节数组 2 是一个数组,我用来自十六进制字符串的 3 个字节填充:

  private static byte[] ssidGetBytes(String ssid)
  {
    BigInteger ssidBigInt = new BigInteger(ssid, 16);

    return ssidBigInt.toByteArray();
  }

怎么可能这样比较:

  if (Arrays.equals(ssidBytes, sha1SsidGetBytes(snSha1)))
  {
  }

大部分时间都有效,但有时无效。字节顺序?

例如对于“6451E6”(十六进制字符串)它工作正常,对于“ABED74”它没有......

【问题讨论】:

  • 您查看过调试器中包含的字节数组吗?您是否可能遇到带符号字节的问题?
  • 如何查看他们是否已签名?

标签: java bytearray


【解决方案1】:

如果你试试这个问题就很明显了:

BigInteger b1 = new BigInteger("6451E6", 16);
BigInteger b2 = new BigInteger("ABED74", 16);

System.out.println(b1.toByteArray().length);
System.out.println(b2.toByteArray().length);

具体来说,ABED74 创建了一个 BigInteger,其字节数组的长度为 4 个字节——所以它当然不会等于任何三字节数组。

直接的解决方法是将 ssidGetBytes 中的 return 语句从

return ssidBigInt.toByteArray();

byte[] ba = ssidBigInt.toByteArray();
return new byte[] { ba[ba.length - 3], ba[ba.length - 2], ba[ba.length - 1] };

【讨论】:

  • 宾果游戏。应该补充一点, toByteArray() 方法旨在(主要)生成与 BigInteger(byte[]) 构造函数兼容的输入。可以说 this 字节编码对于构造函数的 String 输入是 one-way:输入字符串的 byte[] 表示不保证与从字符串创建的 BigInteger 的 byte[] 表示(因为后者可能携带额外的信息,如幅度。)
【解决方案2】:

您通过 BigInteger 解析十六进制字符串的方法基本上是有缺陷的。例如,new BigInteger("ABED74").toByteArray() 返回一个 4 个字节的数组,而不是三个字节。虽然您可以解决这个问题,但您基本上不会尝试做任何涉及 BigInteger 值的事情......您只是尝试解析十六进制。

我建议你使用Apache Codec 库进行解析:

byte[] array = (byte[]) new Hex().decode(text);

(Apache Codec 的 API 有一些不足之处,但它确实有效。)

【讨论】:

  • 那我猜这就是问题所在?有没有其他方法可以将十六进制字符串(长度为 6)解析为 3 个字节的数组?
  • @tersmitten:是的,正如我所说:使用旨在将十六进制字符串解析为字节的东西,而不是为了完成更大的任务而碰巧这样做。当然,您不必使用第三方库:如果您愿意,可以很容易地编写一个解析十六进制的方法。
  • @tersmitten:显然不是:)
【解决方案3】:

来自 javadoc(重点是我的):

http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigInteger.html#toByteArray%28%29

返回一个字节数组,其中包含 二进制补码表示 这个大整数。字节数组将 采用大端字节序:最 有效字节在第零位 元素。该数组将包含 所需的最小字节数 表示这个 BigInteger,包括 至少一个符号位,即 (ceil((this.bitLength() + 1)/8))。 (这种表示是兼容的 使用 (byte[]) 构造函数。)

您正在使用的 ByteInteger(String,radix) 构造函数内部正在进行大量计算,这并不能保证构造的 BigInteger 将生成一个字节数组(通过其 toByteArray() 方法)与字符串的 getBytes() 编码。

toByteArray() 的输出旨在(主要)用作 BigInteger 的 (byte[]) 构造函数的输入。它不保证其他用途。

这样看:toByteArray() 的输出是 BigInteger 对象的字节表示形式以及其中的所有内容,包括幅度等内部属性。这些属性在输入字符串中不存在,但在构建 BitInteger 对象期间计算。

这将与输入字符串的字节表示不兼容只携带用于创建 BigInteger 的初始数值

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-02
    • 2010-11-26
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2010-09-07
    相关资源
    最近更新 更多