【问题标题】:How to convert a hexadecimal string to Uint8Array and back in JavaScript?如何将十六进制字符串转换为 Uint8Array 并返回 JavaScript?
【发布时间】:2023-03-29 17:17:01
【问题描述】:

我想将像 bada55 这样的十六进制字符串转换为 Uint8Array 并再次转换回来。

【问题讨论】:

    标签: javascript ramda.js


    【解决方案1】:

    原版JS:

    const fromHexString = hexString =>
      new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    
    const toHexString = bytes =>
      bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
    
    console.log(toHexString(new Uint8Array([0, 1, 2, 42, 100, 101, 102, 255])))
    console.log(fromHexString('0001022a646566ff'))
    

    注意:此方法信任其输入。如果提供的输入长度为 0,则会引发错误。如果十六进制编码缓冲区的长度不能被 2 整除,则将解析最后一个字节,就好像它前面带有 0(例如,aaa 被解释为 aa0a)。

    如果十六进制可能格式错误或为空(例如用户输入),请在调用此方法之前检查其长度并处理错误,例如:

    const missingLetter = 'abc';
    if(missingLetter.length === 0 || missingLetter.length % 2 !== 0){
      throw new Error(`The string "${missingLetter}" is not valid hex.`)
    }
    fromHexString(missingLetter);
    

    来源:Libauth 库 (hexToBin method)

    【讨论】:

    • 我遇到的这个答案似乎有一个问题..即
    • 抛出错误的条件不对,应该倒过来为if(missingLetter.length % 2 !== 0) {
    • 如果提供的十六进制字符串长度为零,fromHexString() 会失败;在这种情况下,match() 返回 null 而不是长度为零的数组,因此对 map() 的调用失败。
    • @MichaelKay - 谢谢,我添加了关于长度为 0 的输入的注释。
    【解决方案2】:

    Node.js

    对于在 Node 上运行的 JavaScript,您可以这样做:

    const hexString = 'bada55';
    
    const hex = Uint8Array.from(Buffer.from(hexString, 'hex'));
    
    const backToHexString = Buffer.from(hex).toString('hex');
    

    (来源:this answer@Teneff,经许可共享)

    【讨论】:

      【解决方案3】:

      这是原生 JavaScript 的解决方案:

      var string = 'bada55';
      var bytes = new Uint8Array(Math.ceil(string.length / 2));
      for (var i = 0; i < bytes.length; i++) bytes[i] = parseInt(string.substr(i * 2, 2), 16);
      console.log(bytes);
      
      var convertedBack = '';
      for (var i = 0; i < bytes.length; i++) {
        if (bytes[i] < 16) convertedBack += '0';
        convertedBack += bytes[i].toString(16);
      }
      console.log(convertedBack);
      

      【讨论】:

        【解决方案4】:

        浏览器(准确模仿 NodeJS 行为)

        我需要在浏览器环境中模仿 NodeJS Buffer.from(x, 'hex') 行为,这就是我想出的。

        当我通过一些基准测试时,它非常快。

        const HEX_STRINGS = "0123456789abcdef";
        const MAP_HEX = {
          0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6,
          7: 7, 8: 8, 9: 9, a: 10, b: 11, c: 12, d: 13,
          e: 14, f: 15, A: 10, B: 11, C: 12, D: 13,
          E: 14, F: 15
        };
        
        // Fast Uint8Array to hex
        function toHex(bytes) {
          return Array.from(bytes || [])
            .map((b) => HEX_STRINGS[b >> 4] + HEX_STRINGS[b & 15])
            .join("");
        }
        
        // Mimics Buffer.from(x, 'hex') logic
        // Stops on first non-hex string and returns
        // https://github.com/nodejs/node/blob/v14.18.1/src/string_bytes.cc#L246-L261
        function fromHex(hexString) {
          const bytes = new Uint8Array(Math.floor((hexString || "").length / 2));
          let i;
          for (i = 0; i < bytes.length; i++) {
            const a = MAP_HEX[hexString[i * 2]];
            const b = MAP_HEX[hexString[i * 2 + 1]];
            if (a === undefined || b === undefined) {
              break;
            }
            bytes[i] = (a << 4) | b;
          }
          return i === bytes.length ? bytes : bytes.slice(0, i);
        }
        

        【讨论】:

          猜你喜欢
          • 2022-07-21
          • 2014-12-04
          • 1970-01-01
          • 2020-03-28
          • 2013-02-07
          • 2017-06-16
          • 2013-04-07
          • 2017-08-23
          • 2014-03-19
          相关资源
          最近更新 更多