How to convert a binary string into a readable string and vice versa with Javascript

How to convert a binary string into a readable string and vice versa with Javascript

A binary code is a representation of a text, computer processor instructions, or other data using a two symbol system, often the binary number system is 0 and 1. The binary code assigns a pattern of binary digits (bits) to each character, instruction, etc. For example, a binary string of eight bits can represent any of 256 possible values and can therefore represent a variety of different items. Although with other languages the conversion from a string into its binary notation ain't so quick and easy with languages like Python or C++ (using bitset<8>), it still achievable with 3 or 4 lines of code.

In this article you will learn how to convert a string into its binary value and a binary value into a human readable string using Javascript.

Tests

In this article we are going to share with you a couple of methods that convert readable strings into its binary representation or binary strings into readable strings. In order to check if those methods work as expected, we are going to test the method on every object stored in the following variable TestBlock:

var TestBlock = [
    {
        binary: "01010010 01100101 01100001 01101100 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01110011 00100000 01100100 01101111 01101110 00100111 01110100 00100000 01100101 01100001 01110100 00100000 01100011 01100001 01100011 01101000 01100101 00101110",
        text: "Real programs don't eat cache."
    },
    {
        binary: "010011010110111101110011011101  0000100000011100000111010101100010011011000110100101100011001000   000110010001101111011011010110000101101001011011100010000001110011011011110110011001110100011101110110000101110010011001010010000001101001011100110010000001100110011100100110010101100101001011000010000001100001011101000010000001101100011001010                         1100001011100110111010000100000011000010111010000100     000011001100110100101110010011100110   11101000010000001100111011011000110000101101110011000110110010100101110",
        text: "Most public domain software is free, at least at first glance."
    },
    {
        binary: "010101000110100     00110111101110011011001010010000001110111011010000110111100100000011001000110111 1001000000110111 00110111101110100001000000111010101101110011001000110010101110010011100110111010001100001011011100110010000100 00001010101011011100110100101111000001000000110000101110010011001010010000001100011011011110110111001100100011001010110110101101110011001010110  0100001000000111010001101111001000000111001001100101011010010110111001110110011001010110111001 110100 00100000011010010111010000101100001000000111000001101111011011110111001001101100011110010010111000100000001011010010110100100000010010000110010101101110011100100111100    10010000001010011011100000110010101101110011000110110010101110010",
        text: "Those who do not understand Unix are condemned to reinvent it, poorly. -- Henry Spencer"
    },
    {
        binary: "01000110010011110101001001010100 0101001001000001010011100010000001101001011100110010000001100110011011110111001000100000011100000110100101110000011001010010000001110011011101000111001001100101011100110111001100100000011001100111001001100101011000010110101101110011001000000110000101101110011001000010000001100011011100 1001111001011100110111010001100001011011000110110001101111011001110111001001100001011100000110100001111001001000000111011101100101011001010110111001101001011001010111001100101110",
        text: "FORTRAN is for pipe stress freaks and crystallography weenies."
    },
    {
        binary: "00101111 01100101 01100001 01110010 01110100 01101000 00100000 01101001 011100    11 00100000 00111001 00111000 00100101 00100000 01100110 01110101 01101100 01101  100 00100000 00101110 00101110 00101110 00100000 01110000 01101100 01100101 01100001 01110011 01100101 00100000 01100100 01100101 01101100 01100101 01110100 01100101 00100000 01100001 0110 1110 011110  01 01101111 01101110 01100101 00100000 01111001 01101111 01110101 00100000 01100011 01100001 01101110 00101110   ",
        text: "/earth is 98% full ... please delete anyone you can."
    }
];

Having said that, let's get started !

Readable string to binary

To convert a human readable string to its binary value, use the following function:

/**
 * Function that converts a string into its binary representation
 * 
 * @see https://gist.github.com/eyecatchup/6742657
 * @author https://github.com/eyecatchup
 */
function stringToBinary(str, spaceSeparatedOctets) {
    function zeroPad(num) {
        return "00000000".slice(String(num).length) + num;
    }

    return str.replace(/[\s\S]/g, function(str) {
        str = zeroPad(str.charCodeAt().toString(2));
        return !1 == spaceSeparatedOctets ? str : str + " "
    });
};

And you can use it easily:

// "01001000 01100101 01101100 01101100 01101111 00100000 01000010 01101001 01101110 01100001 01110010 01111001 00100000 01010111 01101111 01110010 01101100 01100100"
stringToBinary("Hello Binary World");

But how does this code works ? The providen string The charCodeAt method returns the Unicode of the first character in a string. The toString() method parses its first argument, and attempts to return a string representation in the specified radix (base). For radixes above 10, the letters of the alphabet indicate numerals greater than 9. For example, for hexadecimal numbers (base 16), a through f are used.

If you provide the second parameters (spaceSeparatedOctets) to 0, then the string won't be "pretty printed" (the octets won't be separated). The test for the stringToBinary method is the following (note that the stringToBinary method adds an empty character at the end of the returned string therefore is recommendable to use the trim method to remove it):

var testsSuccesfullyExecuted = 0;
var testErrors = [];

TestBlock.forEach(function(item , index){
    var processedBinaryString = item.binary;
    // Removes the spaces from the binary string
    processedBinaryString = processedBinaryString.replace(/\s+/g, '');
     // Pretty (correct) print binary (add a space every 8 characters)
    processedBinaryString = processedBinaryString.match(/.{1,8}/g).join(" ");

    // Remove spaces at the end of the stringToBinary generated string
    if(stringToBinary(item.text).trim() == processedBinaryString){
        console.log("Test ${"+ index +"} passes");
        testsSuccesfullyExecuted++;
    }else{
        testErrors.push(index);
    }
});

if(testsSuccesfullyExecuted == TestBlock.length){
    console.log("Test suite succesfully executed with no errors");
}else{
    console.error("Test failed with : " + JSON.stringify(testErrors));
}

Providing the following output in the console:

Test ${0} passes
Test ${1} passes
Test ${2} passes
Test ${3} passes
Test ${4} passes
Test suite succesfully executed with no errors

With a standard benchmark executed in a personal computer with the following specifications:

  • Windows 10 Pro 64-bit (10.0, Build 14393) - Chrome Version 56.0.2924.87 (64-bit)
  • Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz (8 CPUs), ~3.6GHz
  • 8192MB RAM

The function stringToBinary needed 1322.53 milliseconds to execute the test 10K times with and average execution per task of 0.13194000000025843 milliseconds.

Binary to readable string

To convert a binary string into a readable string, you can use any of the 2 following methods binaryToString or binaryAgent:

Option 1

This function removes all the empty spaces of the string and will split it into blocks of 8 characters that will be joined into a single string. Then the String.fromCharCode will do the trick for you:

function binaryToString(str) {
    // Removes the spaces from the binary string
    str = str.replace(/\s+/g, '');
    // Pretty (correct) print binary (add a space every 8 characters)
    str = str.match(/.{1,8}/g).join(" ");

    var newBinary = str.split(" ");
    var binaryCode = [];

    for (i = 0; i < newBinary.length; i++) {
        binaryCode.push(String.fromCharCode(parseInt(newBinary[i], 2)));
    }
    
    return binaryCode.join("");
}

And the usage:

// Both of them return: "Hello Binary World"
binaryToString("0100100001100101011011000110110001101111001000000100001001101001011011100110000101110010011110010010000001010111011011110111001001101100011001000010000000100001");
binaryToString("01001000 01100101 01101100 01101100 01101111 00100000 01000010 01101001 01101110 01100001 01110010 01111001 00100000 01010111 01101111 01110010 01101100 01100100 00100000 00100001");

The test code for binaryToString is the following:

var testsSuccesfullyExecuted = 0;
var testErrors = [];

TestBlock.forEach(function(item , index){
    if(binaryToString(item.binary) == item.text){
        console.log("Test ${"+ index +"} passes");
        testsSuccesfullyExecuted++;
    }else{
        testErrors.push(index);
    }
});

if(testsSuccesfullyExecuted == TestBlock.length){
    console.log("Test suite succesfully executed with no errors");
}else{
    console.error("Test failed with : " + JSON.stringify(testErrors));
}

The following test will output the following content in the console:

Test ${0} passes
Test ${1} passes
Test ${2} passes
Test ${3} passes
Test ${4} passes
Test suite succesfully executed with no errors

Option 2

In the same way the first function does, all the empty spaces will be removed and the string will be divided into blocks of 8 characters to be finally joined.

function binaryAgent(str) {
     // Removes the spaces from the binary string
     str = str.replace(/\s+/g, '');
     // Pretty (correct) print binary (add a space every 8 characters)
     str = str.match(/.{1,8}/g).join(" ");

     return str.split(" ").map(function (elem) {
         return String.fromCharCode(parseInt(elem, 2));
     }).join("");
}

And the usage:

// Both of them return: "Hello Binary World"
binaryAgent("0100100001100101011011000110110001101111001000000100001001101001011011100110000101110010011110010010000001010111011011110111001001101100011001000010000000100001");
binaryAgent("01001000 01100101 01101100 01101100 01101111 00100000 01000010 01101001 01101110 01100001 01110010 01111001 00100000 01010111 01101111 01110010 01101100 01100100 00100000 00100001");

The test code for binaryAgent is the following:

var testsSuccesfullyExecuted = 0;
var testErrors = [];

TestBlock.forEach(function(item , index){
    if(binaryAgent(item.binary) == item.text){
        console.log("Test ${"+ index +"} passes");
        testsSuccesfullyExecuted++;
    }else{
        testErrors.push(index);
    }
});

if(testsSuccesfullyExecuted == TestBlock.length){
    console.log("Test suite succesfully executed with no errors");
}else{
    console.error("Test failed with : " + JSON.stringify(testErrors));
}

The following test will output the following content in the console:

Test ${0} passes
Test ${1} passes
Test ${2} passes
Test ${3} passes
Test ${4} passes
Test suite succesfully executed with no errors

Benchmark

The result of a standard benchmark (executed 10K times) with a personal computer with the following specifications:

  • Windows 10 Pro 64-bit (10.0, Build 14393) - Chrome Version 56.0.2924.87 (64-bit)
  • Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz (8 CPUs), ~3.6GHz
  • 8192MB RAM

has generated the following result:

Method Total time (MS) Average time (MS) / Task
binaryToString (Option 1) 1068.54 0.10662899999999208
binaryAgent (Option 2) 1304.80 0.13019300000001968

As you can see the first method is slightly faster than the second.

Happy coding !

Become a more social person