1

我试图用最短的字符串表示 MD5 哈希的结果。将它变成一个十六进制字符串并让 G 到 Z 浪费掉似乎是一种浪费。

我的一个想法是将输入的 MD5 散列作为一个字节数组并BigInt用它构造一个。然后我可以调用toString(36),并在字符串中以 base-36 形式获取数字(-?[0-9a-z]*,数字可以是正数或负数)。这个对我有用。

问题是,我不确定 aBigInt可以用任何字节数组构造,而且我无法通过测试来证明它(至少不能及时!)。我假设是这样,因为我知道 BigInt 可以是任意大小。在我确定它适用于所有可能的输出之前,我不能使用这种方法。那么,谁能告诉我它是否适用于所有输入(或者如何轻松转换字节数组以便它可以在基数 36 中表示)。

澄清:我有实现,我在询问整个域的行为(即 00000000000000000000000000000000 到 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

4

2 回答 2

3

基于您上面的反馈,以下实现将可靠地编码/解码任意字节数组:

package blevins.example

object BigIntEncoder {
  val radix = 36

  implicit def byteArrayToString(ba: Array[Byte]): String = {
    new java.math.BigInteger(addByte(ba)).toString(radix)
  }

  implicit def stringToByteArray(s: String): Array[Byte] = {
    stripByte(new java.math.BigInteger(s, radix).toByteArray)
  }

  def addByte(ba: Array[Byte]): Array[Byte] = {
    val h = new Array[Byte](1)
    h(0) = 0x01
    h ++ ba
  }

  def stripByte(ba: Array[Byte]): Array[Byte] = {
    ba.slice(1,ba.size)
  }

}

请注意,我们在数组的头部添加了一个额外的 0x01 字节,以避免因获取字节数组的二补码而产生任何副作用。

编辑:证明这一点所涉及的测试记录在这里:http ://cleverlytitled.blogspot.com/2009/10/scalacheck.html

于 2009-10-30T03:55:45.917 回答
0

Base64编码不会比Base36短吗?你可以在周围找到很多实现。

但是,要真正回答这个问题:

  // Make a big randomly-filled byte array
  val random = scala.util.Random
  val arraySize = 8543
  val bytes: Array[Byte] = new Array[Byte](arraySize) // make some big array
  random.nextBytes(bytes) // fill it randomly

  // Make a BigInt out of it and the corresponding base36 string representation
  val bi: BigInt = new BigInt(new java.math.BigInteger(bytes))
  val strRep: String = bi.toString(36)

  // Make a new BigInt out of the string rep.  Does it match?
  val bi2: BigInt = new BigInt(new java.math.BigInteger(strRep, 36))
  if (bi == bi2) {
      println("yippee!!")
  }

  // Make a new byte array out of the BigInt.  Does it match the original array?
  val bytes2: Array[Byte] = bi2.toByteArray
  if (bytes deepEquals bytes2) {
      println("yippee again!!")
  }
于 2009-10-29T18:10:32.787 回答