Byte array to Hex string conversion in javascript

前端 未结 7 750
礼貌的吻别
礼貌的吻别 2020-12-30 21:30

I have a byte array of the form [4,-101,122,-41,-30,23,-28,3,..] which I want to convert in the form 6d69f597b217fa333246c2c8 I\'m using below func

相关标签:
7条回答
  • 2020-12-30 21:55

    A more concise and performant (see https://jsperf.com/byte-array-to-hex-string) alternative using Array.reduce():

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

    (Also without "& 0xFF" because in my opinion if an array is passed in that contains values larger than 255, the output should be messed up, so that the user can more easily see that their input was wrong.)

    0 讨论(0)
  • 2020-12-30 21:59

    You need to pad the hex conversion with the appropriate number of leading zeroes.

    0 讨论(0)
  • 2020-12-30 22:01

    When converting a byte array to a hex array, we have to consider how they can be signed numbers. If so, we gotta convert them to decimal numbers first. signed numbers to decimal conversion. Then, we can use the .toString(16) method to convert it to hex.

    const hexArr = byteArr.map((byte) => {
        if (byte < 0) {
          byte = -((byte ^ 0xff) + 1); //converting 2s complement to a decimal number
        }
        //add padding at the start to ensure it's always 2 characters long otherwise '01' will be '1'
        return byte.toString(16).padStart(2, '0'); 
    });
    
    0 讨论(0)
  • 2020-12-30 22:12

    Using map() won't work if the input is of a type like Uint8Array: the result of map() is also Uint8Array which can't hold the results of string conversion.

    function toHexString(byteArray) {
      var s = '0x';
      byteArray.forEach(function(byte) {
        s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
      });
      return s;
    }
    
    0 讨论(0)
  • 2020-12-30 22:12

    Since this is the first Google hit for "js byte to hex" and I needed some time to understand the function of Bergi, I rewrote the function and added some comments that made it easier for me to understand:

    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('');
    }
    
    • For more information about the const unsignedByte = byte & 0xff-part, check What does AND 0xFF do?.
    • Array.from is not available in every browser (e.g. not in IE11), check How to convert a JavaScript Typed Array into a JavaScript Array for more information

    The OP forgot to add the leading 0 for numbers that can be displayed with only 4 bits.

    0 讨论(0)
  • 2020-12-30 22:18

    All of the previous solutions work but they all require the creation of many strings and concatenation and slicing of the created strings. I got thinking there has to be a better way to go about it now that there are typed arrays. I originally did this using node and then commented out the lines that use Buffer and changed them to TypedArrays so it would work in a browser too.

    It's more code but it's significantly faster, at least in the quick jsperf I put together. The string manipulation version in the accepted answer performed 37000 ops/sec while the code below managed 317000 ops/sec. There is a lot of hidden overhead in creating string objects.

    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 讨论(0)
提交回复
热议问题