是否有一种普遍接受的技术可以有效地将JavaScript字符串转换为arraybuffer,反之亦然?具体来说,我希望能够将ArrayBuffer的内容写入localStorage,然后再将其读回来。


当前回答

使用splat unpacking代替loops:

arrbuf =新uint8阵列([104、101、108、108、111]) text = String.fromCharCode(.. arrbuf) console . log(文本)

对于子字符串,可以使用arrbuf.slice()。

其他回答

在使用了mangini的从ArrayBuffer转换到String的解决方案- ab2str(这是我发现的最优雅和有用的一个-谢谢!)之后,我在处理大型数组时遇到了一些问题。更具体地说,调用String.fromCharCode.apply(null, new Uint16Array(buf));抛出错误:

传递给Function.prototype.apply的参数数组太大。

为了解决它(绕过),我决定处理输入ArrayBuffer块。所以修改后的解是:

function ab2str(buf) {
   var str = "";
   var ab = new Uint16Array(buf);
   var abLen = ab.length;
   var CHUNK_SIZE = Math.pow(2, 16);
   var offset, len, subab;
   for (offset = 0; offset < abLen; offset += CHUNK_SIZE) {
      len = Math.min(CHUNK_SIZE, abLen-offset);
      subab = ab.subarray(offset, offset+len);
      str += String.fromCharCode.apply(null, subab);
   }
   return str;
}

块大小设置为2^16,因为这是我发现在我的开发环境中工作的大小。设置一个更高的值会导致同样的错误再次发生。可以通过将CHUNK_SIZE变量设置为不同的值来更改它。偶数是很重要的。

性能注意事项—我没有对此解决方案进行任何性能测试。但是,由于它基于前面的解决方案,并且可以处理大型数组,所以我认为没有理由不使用它。

对于node.js和使用https://github.com/feross/buffer的浏览器

function ab2str(buf: Uint8Array) {
  return Buffer.from(buf).toString('base64');
}
function str2ab(str: string) {
  return new Uint8Array(Buffer.from(str, 'base64'))
}

注意:这里的解决方案对我不起作用。我需要支持node.js和浏览器,只是序列化UInt8Array到一个字符串。我可以将它序列化为一个数字[],但这会占用不必要的空间。有了这个解决方案,我不需要担心编码,因为它是base64。以防其他人也有同样的问题……我的意见

从emscripten:

function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
  if (!(maxBytesToWrite > 0)) return 0;
  var startIdx = outIdx;
  var endIdx = outIdx + maxBytesToWrite - 1;
  for (var i = 0; i < str.length; ++i) {
    var u = str.charCodeAt(i);
    if (u >= 55296 && u <= 57343) {
      var u1 = str.charCodeAt(++i);
      u = 65536 + ((u & 1023) << 10) | u1 & 1023
    }
    if (u <= 127) {
      if (outIdx >= endIdx) break;
      outU8Array[outIdx++] = u
    } else if (u <= 2047) {
      if (outIdx + 1 >= endIdx) break;
      outU8Array[outIdx++] = 192 | u >> 6;
      outU8Array[outIdx++] = 128 | u & 63
    } else if (u <= 65535) {
      if (outIdx + 2 >= endIdx) break;
      outU8Array[outIdx++] = 224 | u >> 12;
      outU8Array[outIdx++] = 128 | u >> 6 & 63;
      outU8Array[outIdx++] = 128 | u & 63
    } else {
      if (outIdx + 3 >= endIdx) break;
      outU8Array[outIdx++] = 240 | u >> 18;
      outU8Array[outIdx++] = 128 | u >> 12 & 63;
      outU8Array[outIdx++] = 128 | u >> 6 & 63;
      outU8Array[outIdx++] = 128 | u & 63
    }
  }
  outU8Array[outIdx] = 0;
  return outIdx - startIdx
}

使用:

stringToUTF8Array('abs', new Uint8Array(3), 0, 4);

Just

const buffer = thisReturnsBuffers();

const blob = new Blob([buffer], {type: 'text/plain; charset=utf-8'});

blob.text().then(text => console.log(text));

Or

const stringVal = "string here";

const blob = new Blob([stringVal], {type: 'text/plain; charset=utf-8'});

blob.arrayBuffer().then(buffer => console.log(buffer));

你们为什么要把事情搞得这么复杂?

假设你有一个arrayBuffer binaryStr:

let text = String.fromCharCode.apply(null, new Uint8Array(binaryStr));

然后你把文本赋值给状态。