我试图用最短的字符串表示MD5哈希的结果。将它变成十六进制字符串并让G到Z变得浪费似乎是浪费。
我有一个想法是将输入的MD5哈希值作为字节数组并用它构造BigInt
。然后我可以调用toString(36)
,并将数字作为字符串中的基数-36(-?[0-9a-z]*
,数字可以是正数或负数)。它对我有用。
问题是,我不确定BigInt
是否可以使用任何字节数组构建,我无法通过测试证明它(至少不能及时证明!)。我是这么认为的,因为我知道BigInt可以是任意大小的。在我确定它适用于所有可能的输出之前,我无法使用此方法。那么,任何人都可以告诉我它是否适用于所有输入(或如何轻松转换字节数组,以便它可以在基数36中表示)。
澄清:我有实施,我问的是整个域的行为(即00000000000000000000000000000000到FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
答案 0 :(得分: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
答案 1 :(得分: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!!")
}