Domanda

Sto cercando di rappresentare il risultato di un hash MD5 nella stringa più breve possibile. Sembra uno spreco trasformarlo in una stringa esadecimale e lasciare che G attraverso Z vada sprecato.

Un'idea che ho avuto è quella di ottenere l'hash MD5 del mio input come una matrice di byte e costruire un BigInt con esso. Posso quindi chiamare toString (36) e ottenere il numero come base-36 in una stringa ( -? [0-9a-z] * , il numero può essere positivo o negativo). Funziona per me.

Il problema è che non sono sicuro che un BigInt possa essere costruito con qualsiasi array di byte e non posso provarlo con i test (almeno non in modo tempestivo!). Lo presumo, perché capisco che un BigInt può avere dimensioni arbitrarie. Non posso usare questo metodo fino a quando non so per certo che funzionerà per tutti i possibili output. Quindi, qualcuno può dirmi se funzionerà per tutti gli input (o come convertire facilmente un array di byte in modo che possa essere rappresentato nella base 36).

Chiarimento : ho l'implementazione, sto chiedendo informazioni sul comportamento sull'intero dominio (ovvero da 0000000000000000000000000000000000 a FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

È stato utile?

Soluzione

Sulla base del tuo feedback sopra, la seguente implementazione codificherà / decodificherà in modo affidabile un array di byte arbitrario:

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

}

Si noti che stiamo aggiungendo un ulteriore 0x01 byte all'intestazione dell'array per evitare che effetti collaterali derivino dal complemento a due dell'array di byte.

EDIT: i test necessari per dimostrarlo sono documentati qui: http: // cleverlytitled.blogspot.com/2009/10/scalacheck.html

Altri suggerimenti

La codifica Base64 non sarebbe più breve di Base36? Puoi trovare molte implementazioni in giro.

Ma, per rispondere effettivamente alla domanda:

  // 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!!")
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top