Pregunta

Estoy tratando de representar el resultado de un hash MD5 en la cadena más corta posible. Parece un desperdicio simplemente convertirlo en una cadena hexadecimal y dejar que G a Z se desperdicie.

Una idea que he tenido es obtener el hash MD5 de mi entrada como una matriz de bytes y construir un BigInt con él. Entonces puedo llamar a toString (36) y obtener el número como base-36 en una cadena ( -? [0-9a-z] * , el número puede ser positivo o negativo) Funciona para mí.

El problema es que no estoy seguro de que se pueda construir un BigInt con cualquier conjunto de bytes, y no puedo probarlo con pruebas (¡al menos no de manera oportuna!). Supongo que sí, porque entiendo que un BigInt puede tener un tamaño arbitrario. No puedo usar este método hasta estar seguro de que funcionará para todas las salidas posibles. Entonces, ¿alguien puede decirme si funcionará para todas las entradas (o cómo convertir fácilmente una matriz de bytes para que pueda representarse en la base 36).

Aclaración : Tengo la implementación, estoy preguntando sobre el comportamiento en todo el dominio (es decir, 00000000000000000000000000000000 a FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

¿Fue útil?

Solución

Basándose en sus comentarios anteriores, la siguiente implementación codificará / decodificará de manera confiable una matriz de bytes arbitraria:

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)
  }

}

Tenga en cuenta que estamos agregando un byte 0x01 adicional al encabezado de la matriz para evitar que los efectos secundarios tomen el complemento de dos de la matriz de bytes.

EDITAR: Las pruebas involucradas para probar esto se documentan aquí: http: // cleverlytitled.blogspot.com/2009/10/scalacheck.html

Otros consejos

¿No sería la codificación Base64 más corta que Base36? Puede encontrar muchas implementaciones alrededor.

Pero, para responder realmente la pregunta:

  // 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!!")
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top