Search code examples
javascriptarraybuffertyped-arrays

JavaScript- convert array buffer to string


Title says it all. I have a jquery serialized data that looks like this:

tarid=value&tarname=value&sel=3

And I want to convert it to ArrayBuffer. After that, I also need to turn it back to its original form again. So how can I do that?


Solution

  • is this enough?

    function stringToArrayBuffer(str){
        if(/[\u0080-\uffff]/.test(str)){
            throw new Error("this needs encoding, like UTF-8");
        }
        var arr = new Uint8Array(str.length);
        for(var i=str.length; i--; )
            arr[i] = str.charCodeAt(i);
        return arr.buffer;
    }
    
    function arrayBufferToString(buffer){
        var arr = new Uint8Array(buffer);
        var str = String.fromCharCode.apply(String, arr);
        if(/[\u0080-\uffff]/.test(str)){
            throw new Error("this string seems to contain (still encoded) multibytes");
        }
        return str;
    }
    

    or do you need real UTF-8 encoding

    Edit: full UTF-8 support

    Beware/Disclaimer: this code is not tested against some foreign implementaion of an UTF-8 encoder or decoder. It may produce wrong results.

    TEST IT YOURSELF, before you use it in production!

    function stringToArrayBuffer(str){
        if(/[\u0080-\uffff]/.test(str)){
            var arr = new Array(str.length);
            for(var i=0, j=0, len=str.length; i<len; ++i){
                var cc = str.charCodeAt(i);
                if(cc < 128){
                    //single byte
                    arr[j++] = cc;
                }else{
                    //UTF-8 multibyte
                    if(cc < 2048){
                        arr[j++] = (cc >> 6) | 192;
                    }else{
                        arr[j++] = (cc >> 12) | 224;
                        arr[j++] = ((cc >> 6) & 63) | 128;
                    }
                    arr[j++] = (cc & 63) | 128;
                }
            }
            var byteArray = new Uint8Array(arr);
        }else{
            var byteArray = new Uint8Array(str.length);
            for(var i = str.length; i--; )
                byteArray[i] = str.charCodeAt(i);
        }
        return byteArray.buffer;
    }
    
    function arrayBufferToString(buffer){
        var byteArray = new Uint8Array(buffer);
        var str = "", cc = 0, numBytes = 0;
        for(var i=0, len = byteArray.length; i<len; ++i){
            var v = byteArray[i];
            if(numBytes > 0){
                //2 bit determining that this is a tailing byte + 6 bit of payload
                if((cc&192) === 192){
                    //processing tailing-bytes
                    cc = (cc << 6) | (v & 63);
                }else{
                    throw new Error("this is no tailing-byte");
                }
            }else if(v < 128){
                //single-byte
                numBytes = 1;
                cc = v;
            }else if(v < 192){
                //these are tailing-bytes
                throw new Error("invalid byte, this is a tailing-byte")
            }else if(v < 224){
                //3 bits of header + 5bits of payload
                numBytes = 2;
                cc = v & 31;
            }else if(v < 240){
                //4 bits of header + 4bit of payload
                numBytes = 3;
                cc = v & 15;
            }else{
                //UTF-8 theoretically supports up to 8 bytes containing up to 42bit of payload
                //but JS can only handle 16bit.
                throw new Error("invalid encoding, value out of range")
            }
    
            if(--numBytes === 0){
                str += String.fromCharCode(cc);
            }
        }
        if(numBytes){
            throw new Error("the bytes don't sum up");
        }
        return str;
    }