web-dev-qa-db-fra.com

Tableau d'octets en conversion de chaîne hexadécimale en javascript

J'ai un tableau d'octets de la forme [4,-101,122,-41,-30,23,-28,3,..] que je souhaite convertir sous la forme 6d69f597b217fa333246c2c8 J'utilise la fonction ci-dessous

function toHexString(bytes) {
  return bytes.map(function(byte) {
    return (byte & 0xFF).toString(16)
  }).join('')
}

ce qui me donne une chaîne de la même forme mais je soupçonne que ce n'est pas une conversion efficace car la chaîne hexadécimale est un peu plus courte que prévu. Je pense que la traduction devrait obtenir "0a10a6dc". Veuillez me dire si je me trompe ou si c'est une bonne conversion mais peut-être que je n'utilise pas le bon tableau d'octets

tableau d'octets 4,-127,45,126,58,-104,41,-27,-43,27,-35,100,-50,-77,93,-16,96,105,-101,-63,48,-105,49,-67,110,111,26,84,67,-89,-7,-50,10,-12,56,47,-49,-42,-11,-8,-96,-117,-78,97,-105,9,-62,-44,-97,-73,113,96,23,112,-14,-62,103,-104,90,-14,117,78,31,-116,-7

Conversion correspondante 4812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ceaf4382fcfd6f5f8a08bb261979c2d49fb771601770f2c267985af2754e1f8cf9

16
Actung

Il vous manque le rembourrage dans la conversion hexadécimale. Vous voudrez utiliser

function toHexString(byteArray) {
  return Array.from(byteArray, function(byte) {
    return ('0' + (byte & 0xFF).toString(16)).slice(-2);
  }).join('')
}

de sorte que chaque octet se transforme en exactement deux chiffres hexadécimaux. Votre sortie attendue serait 04812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ce0af4382fcfd6f5f8a08bb2619709c2d49fb771601770f2c267985af2754e1f8cf9

42
Bergi

L'utilisation de map() ne fonctionnera pas si l'entrée est d'un type comme Uint8Array: Le résultat de map() est aussi Uint8Array Qui ne peut pas contenir les résultats de la conversion de chaîne.

function toHexString(byteArray) {
  var s = '0x';
  byteArray.forEach(function(byte) {
    s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
  });
  return s;
}
6
grantpatterson

Une alternative plus concise et performante (voir https://jsperf.com/byte-array-to-hex-string ) en utilisant Array.reduce ():

function toHexString(byteArray) {
  return byteArray.reduce((output, elem) => 
    (output + ('0' + elem.toString(16)).slice(-2)),
    '');
}

(Aussi sans "0xFF" car à mon avis, si un tableau contenant des valeurs supérieures à 255 est transmis, la sortie doit être gâchée, afin que l'utilisateur puisse plus facilement voir que son entrée était incorrecte.)

6
AndyO

Comme il s'agit du premier hit de Google pour "js byte to hex" et que j'avais besoin de temps pour comprendre la fonction de Bergi, j'ai réécrit la fonction et ajouté quelques commentaires qui me facilitaient la compréhension:

function byteToHex(byte) {
  // convert the possibly signed byte (-128 to 127) to an unsigned byte (0 to 255).
  // if you know, that you only deal with unsigned bytes (Uint8Array), you can omit this line
  const unsignedByte = byte & 0xff;

  // If the number can be represented with only 4 bits (0-15), 
  // the hexadecimal representation of this number is only one char (0-9, a-f). 
  if (unsignedByte < 16) {
    return '0' + unsignedByte.toString(16);
  } else {
    return unsignedByte.toString(16);
  }
}

// bytes is an typed array (Int8Array or Uint8Array)
function toHexString(bytes) {
  // Since the .map() method is not available for typed arrays, 
  // we will convert the typed array to an array using Array.from().
  return Array.from(bytes)
    .map(byte => byteToHex(byte))
    .join('');
}

L'OP a oublié d'ajouter le premier 0 pour les nombres qui peuvent être affichés avec seulement 4 bits.

4
Putzi San

Vous devez remplir la conversion hexadécimale avec le nombre approprié de zéros non significatifs.

1
void

Pour garder votre code propre, vous pouvez utiliser les bibliothèques existantes, par exemple array-buffer-to-hex . Exemple:

const arrayBufferToHex = require('array-buffer-to-hex')
const crypto = require('crypto')

const bytes = crypto.randomBytes(10)

console.log(arrayBufferToHex(bytes)) // => "557f694f76c628fd6acb"
0
ns16

Toutes les solutions précédentes fonctionnent mais elles nécessitent toutes la création de nombreuses chaînes et la concaténation et le découpage des chaînes créées. J'ai pensé qu'il devait y avoir une meilleure façon de procéder maintenant qu'il y a des tableaux typés. À l'origine, j'ai fait cela en utilisant le nœud, puis j'ai commenté les lignes qui utilisent Buffer et les ai modifiées en TypedArrays afin que cela fonctionne également dans un navigateur.

C'est plus de code mais c'est beaucoup plus rapide, au moins dans le quick jsperf j'ai mis ensemble. La version de manipulation de chaîne dans la réponse acceptée a effectué 37 000 opérations/s tandis que le code ci-dessous gérait 317 000 opérations/s. Il y a beaucoup de frais généraux cachés dans la création d'objets chaîne.

function toHexString (byteArray) {
  //const chars = new Buffer(byteArray.length * 2);
  const chars = new Uint8Array(byteArray.length * 2);
  const alpha = 'a'.charCodeAt(0) - 10;
  const digit = '0'.charCodeAt(0);

  let p = 0;
  for (let i = 0; i < byteArray.length; i++) {
      let nibble = byteArray[i] >>> 4;
      chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;
      nibble = byteArray[i] & 0xF;
      chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;    
  }

  //return chars.toString('utf8');
  return String.fromCharCode.apply(null, chars);
}
0
bmacnaughton