Question

J'essaie de représenter le résultat d'un hachage MD5 dans la chaîne la plus courte possible. Il semble inutile de le transformer en une chaîne hexagonale et de laisser G à Z se perdre.

Une des idées que j'ai eu est d'obtenir le hachage MD5 de mon entrée sous forme de tableau d'octets et de construire un BigInt avec ce dernier. Je peux ensuite appeler toString (36) et obtenir le numéro sous forme de base-36 dans une chaîne ( -? [0-9a-z] * , le numéro peut être positif ou négatif). Cela fonctionne pour moi.

Le problème, c'est que je ne suis pas sûr qu'un BigInt puisse être construit avec un tableau d'octets, et je ne peux pas le prouver avec des tests (du moins pas à temps!). Je suppose que oui, car je comprends qu'un BigInt peut être de taille arbitraire. Je ne peux pas utiliser cette méthode avant de savoir avec certitude que cela fonctionnera pour toutes les sorties possibles. Alors, quelqu'un peut-il me dire si cela fonctionnera pour toutes les entrées (ou comment convertir facilement un tableau d'octets afin qu'il puisse être représenté en base 36).

Clarification : j'ai l'implémentation, je vous pose des questions sur le comportement de l'ensemble du domaine (00000000000000000000000000000000 à FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

Était-ce utile?

La solution

En vous basant sur vos commentaires ci-dessus, la mise en œuvre suivante codera / décodera de manière fiable un tableau d'octets arbitraire:

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

}

Notez que nous ajoutons un octet supplémentaire 0x01 à la tête du tableau pour éviter tout effet secondaire résultant de la prise du complément à deux du tableau d'octets.

EDIT: les tests nécessaires pour prouver cette erreur sont documentés ici: http: // cleverlytitled.blogspot.com/2009/10/scalacheck.html

Autres conseils

Le codage Base64 ne serait-il pas plus court que Base36? Vous pouvez trouver de nombreuses implémentations autour.

Mais pour répondre à la question:

  // 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!!")
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top