Pergunta

Eu estou tentando representar o resultado de um hash MD5 no menor corda possível. Parece um desperdício apenas para transformá-lo em uma string hex e deixe G a Z ir para o lixo.

Uma idéia que eu tive é obter o hash MD5 da minha entrada como um array de bytes e construindo uma BigInt com ele. Posso, então, chamar toString(36), e obter o número como uma base-36 em um string (-?[0-9a-z]*, o número pode ser positivo ou negativo). Ele funciona para mim.

O problema é que eu não tenho certeza de que um BigInt pode ser construído com qualquer matriz de bytes, e eu não posso provar isso com testes (pelo menos não de uma forma oportuna!). Presumo que sim, porque eu entendo que um BigInt pode ser de tamanho arbitrário. Eu não pode usar esse método até que eu sei com certeza que ele vai trabalhar para todas as saídas possíveis. Então, alguém pode me dizer se ele vai funcionar para todas as entradas (ou como converter facilmente uma matriz de bytes para que ele possa ser representado na base 36).

Clarificação : Eu tenho a implementação, eu estou perguntando sobre o comportamento ao longo do todo o domínio (ou seja 00000000000000000000000000000000 para FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

Foi útil?

Solução

Com base no seu feedback acima, a seguinte implementação será confiável codificar / decodificar uma matriz de bytes arbitrário:

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

}

Note que estamos adicionando um 0x01 byte extra para a cabeça da matriz para evitar quaisquer efeitos secundários de tomar a dois complemento da matriz de bytes.

EDIT: O teste envolveu a provar isso está documentado aqui: http: // cleverlytitled.blogspot.com/2009/10/scalacheck.html

Outras dicas

Será que não codificação Base64 ser inferior a Base36? Você pode encontrar muitas das implementações ao redor.

Mas, para realmente responder à pergunta:

  // 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top