Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ArrayBuffer to String, String to ArrayBuffer Method(s)

Tags:

javascript

This question has received answers in the past, but I would definitely say that it is still not answered.

There is almost documentation on ArrayBuffers in general, let alone on specific applications. I have been researching for days to no avail on this.

Essentially I need to try to convert an ArrayBuffer that I got from a file reader (here: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer) to a string, and then convert that string back to the same ArrayBuffer.

I have tried these methods for example

function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
  var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
  var bufView = new Uint16Array(buf);
  for (var i=0, strLen=str.length; i<strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return b

I get the following error: "byte length of Uint16Array should be a multiple of 2"

I also tried the following

function StringToUint8Array(string) {
    var binary, binLen, buffer, chars, i, _i;
    binary = StringToBinary(string);
    binLen = binary.length;
    buffer = new ArrayBuffer(binLen);
    chars  = new Uint8Array(buffer);
    for (i = _i = 0; 0 <= binLen ? _i < binLen : _i > binLen; i = 0 <= binLen ? ++_i : --_i) {
        chars[i] = String.prototype.charCodeAt.call(binary, i);
    }
    return chars;
}

function ArrayBufferToString(buffer) {
    return BinaryToString(String.fromCharCode.apply(null, Array.prototype.slice.apply(new Uint8Array(buffer))));
}

function StringToArrayBuffer(string) {
    return StringToUint8Array(string).buffer;
}

function BinaryToString(binary) {
    var error;

    try {
        return decodeURIComponent(escape(binary));
    } catch (_error) {
        error = _error;
        if (error instanceof URIError) {
            return binary;
        } else {
            throw error;
        }
    }
}

function StringToBinary(string) {
    var chars, code, i, isUCS2, len, _i;

    len = string.length;
    chars = [];
    isUCS2 = false;
    for (i = _i = 0; 0 <= len ? _i < len : _i > len; i = 0 <= len ? ++_i : --_i) {
        code = String.prototype.charCodeAt.call(string, i);
        if (code > 255) {
            isUCS2 = true;
            chars = null;
            break;
        } else {
            chars.push(code);
        }
    }
    if (isUCS2 === true) {
        return unescape(encodeURIComponent(string));
    } else {
        return String.fromCharCode.apply(null, Array.prototype.slice.apply(chars));
    }
}

And received this error: Maximum call stack size exceeded

It seems that there are just no good methods for the following conversions: AB --> String || String -> AB

like image 618
Lao Tzu Avatar asked Dec 04 '22 00:12

Lao Tzu


2 Answers

Most browsers now have TextEncoder and TextDecoder, and Node has util.TextEncoder and util.TextDecoder. This WHATWG standard provides straightforward methods to convert between byte arrays (which have a buffer attribute) and strings:

const str = new TextDecoder().decode(byteArray);
const byteArray = new TextEncoder().encode(str);
const buffer = byteArray.buffer;
like image 122
John Avatar answered Dec 24 '22 14:12

John


There is an asynchronous way using Blob and FileReader.

You can specify any valid encoding.

function arrayBufferToString( buffer, encoding, callback ) {
    var blob = new Blob([buffer],{type:'text/plain'});
    var reader = new FileReader();
    reader.onload = function(evt){callback(evt.target.result);};
    reader.readAsText(blob, encoding);
}

function stringToArrayBuffer( string, encoding, callback ) {
    var blob = new Blob([string],{type:'text/plain;charset='+encoding});
    var reader = new FileReader();
    reader.onload = function(evt){callback(evt.target.result);};
    reader.readAsArrayBuffer(blob);
}


//example:
var buf = new Uint8Array([65,66,67]);
arrayBufferToString(buf, 'UTF-8', console.log.bind(console)); //"ABC"

stringToArrayBuffer('ABC', 'UTF-8', console.log.bind(console)); //[65,66,67]
like image 29
cuixiping Avatar answered Dec 24 '22 15:12

cuixiping