【问题标题】:Converting byte array to string in javascript在javascript中将字节数组转换为字符串
【发布时间】:2024-01-17 05:12:01
【问题描述】:

如何将字节数组转换为字符串?

我发现这些功能相反:

function string2Bin(s) {
    var b = new Array();
    var last = s.length;

    for (var i = 0; i < last; i++) {
        var d = s.charCodeAt(i);
        if (d < 128)
            b[i] = dec2Bin(d);
        else {
            var c = s.charAt(i);
            alert(c + ' is NOT an ASCII character');
            b[i] = -1;
        }
    }
    return b;
}

function dec2Bin(d) {
    var b = '';

    for (var i = 0; i < 8; i++) {
        b = (d%2) + b;
        d = Math.floor(d/2);
    }

    return b;
}

但是如何让这些功能以另一种方式工作?

谢谢。

【问题讨论】:

标签: javascript casting


【解决方案1】:

您需要将每个八位字节解析回数字,并使用该值来获取字符,如下所示:

function bin2String(array) {
  var result = "";
  for (var i = 0; i < array.length; i++) {
    result += String.fromCharCode(parseInt(array[i], 2));
  }
  return result;
}

bin2String(["01100110", "01101111", "01101111"]); // "foo"

// Using your string2Bin function to test:
bin2String(string2Bin("hello world")) === "hello world";

编辑:是的,您当前的string2Bin 可以写得更短:

function string2Bin(str) {
  var result = [];
  for (var i = 0; i < str.length; i++) {
    result.push(str.charCodeAt(i).toString(2));
  }
  return result;
}

但是通过查看您链接的文档,我认为 setBytesParameter 方法期望 blob 数组包含十进制数字,而不是 位字符串,因此您可以编写如下内容:

function string2Bin(str) {
  var result = [];
  for (var i = 0; i < str.length; i++) {
    result.push(str.charCodeAt(i));
  }
  return result;
}

function bin2String(array) {
  return String.fromCharCode.apply(String, array);
}

string2Bin('foo'); // [102, 111, 111]
bin2String(string2Bin('foo')) === 'foo'; // true

【讨论】:

  • 感谢您的超快速响应。几个问题... 1) 您的 bin2String 函数令人印象深刻 - 只有 5 行代码。是否可以更改 string2bin 函数以使用更多 Javascript 函数来缩短函数和子函数? .....
  • 2) 我需要这些转换的原因是因为我正在捕获一个签名,并且我必须对其进行转换以填充数据库中的 BLOB 字段。问题是,虽然这两个功能有效,但还有其他问题。主要的是,当我从数据库中检索 BLOB 时,它会进入字节数组对象。但是,当我通过原始函数运行 BLOB 后将其写入数据库时​​,它不是字节数组对象。这可能是导致问题的原因。有什么想法吗?
  • dcx.sybase.com/index.html#1101en/ulmbus_en11/… 这是我用来设置数据的语法。
  • String.fromCharCode.apply(String, array) 对于 Safari 中很长的字符串是不安全的。 JavaScriptCore 中有一个问题,这意味着函数不能接受超过 65536 个参数,否则会抛出 RangeError。它还将浏览器锁定在比这略小的数组上。见bugs.webkit.org/show_bug.cgi?id=80797
  • 多字节 utf-8 字符失败,即:bin2String([0xE2, 0x98, 0xB9])
【解决方案2】:

ES6 更新

现在,字符串 'foo' 也等于 String.fromCharCode(...[102, 111, 111])

原答案

只需将您的字节数组apply 发送到String.fromCharCode。例如

String.fromCharCode.apply(null, [102, 111, 111]) 等于'foo'。

MDN 文档here.

警告:适用于小于 65535 的数组 - MDN 文档here

【讨论】:

  • 这已经被 6 年前接受的答案证明了。
  • 啊,确实,我错过了那句话。基本上我一直在寻找一个简短的单行字,但我忽略了那个冗长且经过编辑的答案(可能太仓促了)。
  • 即使是重新迭代,它的简洁性使它比公认的答案更好。
【解决方案3】:

尝试新的文本编码 API:

// create an array view of some valid bytes
let bytesView = new Uint8Array([104, 101, 108, 108, 111]);

console.log(bytesView);

// convert bytes to string
// encoding can be specfied, defaults to utf-8 which is ascii.
let str = new TextDecoder().decode(bytesView); 

console.log(str);

// convert string to bytes
// encoding can be specfied, defaults to utf-8 which is ascii.
let bytes2 = new TextEncoder().encode(str);

// look, they're the same!
console.log(bytes2);
console.log(bytesView);

【讨论】:

【解决方案4】:

这应该可行:

String.fromCharCode(...array);

或者

String.fromCodePoint(...array)

【讨论】:

  • 又短又甜 ;)
【解决方案5】:

string2Bin 可以写得更简洁更多,并且没有任何循环,启动!

function string2Bin ( str ) {
    return str.split("").map( function( val ) { 
        return val.charCodeAt( 0 ); 
    } );
}

【讨论】:

  • 很想知道添加的函数调用是否会减慢速度。
  • 它仍然有一个循环,它只是隐藏在 map() 中。
【解决方案6】:

我认为这样会更有效率:

function toBinString (arr) {
    var uarr = new Uint8Array(arr.map(function(x){return parseInt(x,2)}));
    var strings = [], chunksize = 0xffff;
    // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
    for (var i=0; i*chunksize < uarr.length; i++){
        strings.push(String.fromCharCode.apply(null, uarr.subarray(i*chunksize, (i+1)*chunksize)));
    }
    return strings.join('');
}

【讨论】:

    【解决方案7】:

    即使我有点晚了,我认为未来的用户分享一些我使用 ES6 所做的单行实现会很有趣。

    根据您的环境或/以及您将如何处理数据,我认为重要的一件事是保留完整的字节值。例如,(5).toString(2) 会给你101,但实际上完整的二进制转换是00000101,这就是为什么你可能需要创建一个leftPad 实现来用前导零填充字符串字节。但您可能根本不需要它,就像其他答案所示。

    如果您运行以下代码 sn-p,您将看到第一个输出是将 abc 字符串转换为字节数组,然后将所述数组重新转换为相应的字符串。

    // For each byte in our array, retrieve the char code value of the binary value
    const binArrayToString = array => array.map(byte => String.fromCharCode(parseInt(byte, 2))).join('')
    
    // Basic left pad implementation to ensure string is on 8 bits
    const leftPad = str => str.length < 8 ? (Array(8).join('0') + str).slice(-8) : str
    
    // For each char of the string, get the int code and convert it to binary. Ensure 8 bits.
    const stringToBinArray = str => str.split('').map(c => leftPad(c.charCodeAt().toString(2)))
    
    const array = stringToBinArray('abc')
    
    console.log(array)
    console.log(binArrayToString(array))

    【讨论】:

      【解决方案8】:

      字符串到字节数组: "FooBar".split('').map(c =&gt; c.charCodeAt(0));

      字节数组转字符串: [102, 111, 111, 98, 97, 114].map(c =&gt; String.fromCharCode(c)).join('');

      【讨论】:

      • 小心,IE不支持这个!
      【解决方案9】:

      回答为时已晚,但如果您的输入是 ASCII 字节的形式,那么您可以尝试以下解决方案:

      function convertArrToString(rArr){
       //Step 1: Convert each element to character
       let tmpArr = new Array();
       rArr.forEach(function(element,index){
          tmpArr.push(String.fromCharCode(element));
      });
      //Step 2: Return the string by joining the elements
      return(tmpArr.join(""));
      }
      
      function convertArrToHexNumber(rArr){
        return(parseInt(convertArrToString(rArr),16));
      }
      

      【讨论】:

        【解决方案10】:

        如果您使用的是 node.js,您可以这样做:

        yourByteArray.toString('base64');
        

        【讨论】:

          【解决方案11】:

          没有找到任何适用于 UTF-8 字符的解决方案。 String.fromCharCode 在遇到 2 字节字符之前很好。

          例如 Hüser 将作为 [0x44,0x61,0x6e,0x69,0x65,0x6c,0x61,0x20,0x48,0xc3,0xbc,0x73,0x65,0x72]

          但是,如果您使用 String.fromCharCode 完成它,您将拥有 Hüser,因为每个字节将分别转换为一个字符。

          解决方案

          目前我正在使用以下解决方案:

          function pad(n) { return (n.length < 2 ? '0' + n : n); }
          function decodeUtf8(data) {
            return decodeURIComponent(
              data.map(byte => ('%' + pad(byte.toString(16)))).join('')
            );
          }
          

          【讨论】:

            【解决方案12】:

            我有一些带有填充字符和其他我不需要的东西的解密字节数组,所以我这样做了(可能不完美,但它适用于我的有限用途)

            var junk = String.fromCharCode.apply(null, res).split('').map(char => char.charCodeAt(0) <= 127 && char.charCodeAt(0) >= 32 ? char : '').join('');
            

            【讨论】:

              【解决方案13】:

              如果您的数组以 UTF-8 编码并且您不能使用 TextDecoder API,因为it is not supported on IE:

              1. 可以使用Mozilla Developer Network website推荐的FastestSmallestTextEncoderDecoder polyfill;
              2. 您也可以使用MDN website提供的此功能:

              function utf8ArrayToString(aBytes) {
                  var sView = "";
                  
                  for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
                      nPart = aBytes[nIdx];
                      
                      sView += String.fromCharCode(
                          nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
                              /* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
                              (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
                          : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
                              (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
                          : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
                              (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
                          : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
                              (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
                          : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
                              (nPart - 192 << 6) + aBytes[++nIdx] - 128
                          : /* nPart < 127 ? */ /* one byte */
                              nPart
                      );
                  }
                  
                  return sView;
              }
              
              let str = utf8ArrayToString([50,72,226,130,130,32,43,32,79,226,130,130,32,226,135,140,32,50,72,226,130,130,79]);
              
              // Must show 2H₂ + O₂ ⇌ 2H₂O
              console.log(str);

              【讨论】:

                【解决方案14】:
                > const stringToBin = (str) => [...str].map(item=>item.charCodeAt())
                > undefined
                > stringToBin('hello')
                > (5) [104, 101, 108, 108, 111]
                > const binToString = (array) => String.fromCharCode(...array) 
                > undefined
                > binToString(stringToBin('hello'))
                > 'hello'
                

                【讨论】:

                  【解决方案15】:

                  我找到的最简单的解决方案是:

                  var text = atob(byteArray);
                  

                  【讨论】:

                    最近更新 更多