Converting byte array to string in javascript

JavascriptCasting

Javascript Problem Overview


How do I convert a byte array into a string?

I have found these functions that do the reverse:

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;
}

But how do I get the functions working the other way?

Thanks.

Shao

Javascript Solutions


Solution 1 - Javascript

You need to parse each octet back to number, and use that value to get a character, something like this:

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";

Edit: Yes, your current string2Bin can be written more shortly:

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

But by looking at the documentation you linked, I think that the setBytesParameter method expects that the blob array contains the decimal numbers, not a bit string, so you could write something like this:

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

Solution 2 - Javascript

ES6 update

Now, string 'foo' also equals String.fromCharCode(...[102, 111, 111])

Original answer

Simply apply your byte array to String.fromCharCode. For example

String.fromCharCode.apply(null, [102, 111, 111]) equals 'foo'.

MDN docs here.

Caveat: works for arrays shorter than 65535 - MDN docs here.

Solution 3 - Javascript

Try the new Text Encoding 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);

Solution 4 - Javascript

This should work:

String.fromCharCode(...array);

Or

String.fromCodePoint(...array)

Solution 5 - Javascript

That string2Bin can be written even more succinctly, and without any loops, to boot!

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

Solution 6 - Javascript

I think this would be more efficient:

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('');
}

Solution 7 - Javascript

Even if I'm a bit late, I thought it would be interesting for future users to share some one-liners implementations I did using ES6.

One thing that I consider important depending on your environment or/and what you will do with with the data is to preserve the full byte value. For example, (5).toString(2) will give you 101, but the complete binary conversion is in reality 00000101, and that's why you might need to create a leftPad implementation to fill the string byte with leading zeros. But you may not need it at all, like other answers demonstrated.

If you run the below code snippet, you'll see the first output being the conversion of the abc string to a byte array and right after that the re-transformation of said array to it's corresponding string.

// 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))

Solution 8 - Javascript

String to byte array: "FooBar".split('').map(c => c.charCodeAt(0));

Byte array to string: [102, 111, 111, 98, 97, 114].map(c => String.fromCharCode(c)).join('');

Solution 9 - Javascript

Too late to answer but if your input is in form of ASCII bytes, then you could try this solution:

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));
}

Solution 10 - Javascript

If you are using node.js you can do this:

yourByteArray.toString('base64');

Solution 11 - Javascript

Didn't find any solution that would work with UTF-8 characters. String.fromCharCode is good until you meet 2 byte character.

For example Hüser will come as [0x44,0x61,0x6e,0x69,0x65,0x6c,0x61,0x20,0x48,0xc3,0xbc,0x73,0x65,0x72]

But if you go through it with String.fromCharCode you will have Hüser as each byte will be converted to a char separately.

Solution

Currently I'm using following solution:

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

Solution 12 - Javascript

I had some decrypted byte arrays with padding characters and other stuff I didn't need, so I did this (probably not perfect, but it works for my limited use)

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

Solution 13 - Javascript

If your array is encoded in UTF-8 and you can't use the TextDecoder API because it is not supported on IE:

  1. You can use the FastestSmallestTextEncoderDecoder polyfill recommended by the Mozilla Developer Network website;
  2. You can use this function also provided at the 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);

Solution 14 - Javascript

> 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'

Solution 15 - Javascript

The simplest solution I've found is:

var text = atob(byteArray);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser385579View Question on Stackoverflow
Solution 1 - JavascriptChristian C. SalvadóView Answer on Stackoverflow
Solution 2 - JavascriptBogdan DView Answer on Stackoverflow
Solution 3 - JavascriptJamesView Answer on Stackoverflow
Solution 4 - JavascriptRouli FremanView Answer on Stackoverflow
Solution 5 - JavascriptcmcnultyView Answer on Stackoverflow
Solution 6 - JavascriptlovasoaView Answer on Stackoverflow
Solution 7 - JavascriptPreviewView Answer on Stackoverflow
Solution 8 - JavascriptZaksBackView Answer on Stackoverflow
Solution 9 - JavascriptindiaadityaView Answer on Stackoverflow
Solution 10 - JavascriptCanerView Answer on Stackoverflow
Solution 11 - JavascriptSoul_manView Answer on Stackoverflow
Solution 12 - JavascriptIgnusFastView Answer on Stackoverflow
Solution 13 - JavascriptRosberg LinharesView Answer on Stackoverflow
Solution 14 - JavascriptDonghua LiuView Answer on Stackoverflow
Solution 15 - JavascriptKyle KrzeskiView Answer on Stackoverflow