Converting between strings and ArrayBuffers

后端 未结 24 1207
慢半拍i
慢半拍i 2020-11-22 04:50

Is there a commonly accepted technique for efficiently converting JavaScript strings to ArrayBuffers and vice-versa? Specifically, I\'d like to be able to write the contents

24条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-22 05:14

    All the following is about getting binary strings from array buffers

    I'd recommend not to use

    var binaryString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));
    

    because it

    1. crashes on big buffers (somebody wrote about "magic" size of 246300 but I got Maximum call stack size exceeded error on 120000 bytes buffer (Chrome 29))
    2. it has really poor performance (see below)

    If you exactly need synchronous solution use something like

    var
      binaryString = '',
      bytes = new Uint8Array(arrayBuffer),
      length = bytes.length;
    for (var i = 0; i < length; i++) {
      binaryString += String.fromCharCode(bytes[i]);
    }
    

    it is as slow as the previous one but works correctly. It seems that at the moment of writing this there is no quite fast synchronous solution for that problem (all libraries mentioned in this topic uses the same approach for their synchronous features).

    But what I really recommend is using Blob + FileReader approach

    function readBinaryStringFromArrayBuffer (arrayBuffer, onSuccess, onFail) {
      var reader = new FileReader();
      reader.onload = function (event) {
        onSuccess(event.target.result);
      };
      reader.onerror = function (event) {
        onFail(event.target.error);
      };
      reader.readAsBinaryString(new Blob([ arrayBuffer ],
        { type: 'application/octet-stream' }));
    }
    

    the only disadvantage (not for all) is that it is asynchronous. And it is about 8-10 times faster then previous solutions! (Some details: synchronous solution on my environment took 950-1050 ms for 2.4Mb buffer but solution with FileReader had times about 100-120 ms for the same amount of data. And I have tested both synchronous solutions on 100Kb buffer and they have taken almost the same time, so loop is not much slower the using 'apply'.)

    BTW here: How to convert ArrayBuffer to and from String author compares two approaches like me and get completely opposite results (his test code is here) Why so different results? Probably because of his test string that is 1Kb long (he called it "veryLongStr"). My buffer was a really big JPEG image of size 2.4Mb.

提交回复
热议问题