Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

binary to string, better than a dictionary?

Objective: Convert binary to string

Example: 0111010001100101011100110111010001100011011011110110010001100101 -> testCode (without space)

I use a dictionary and my function, i search a better way and more efficient

from textwrap import wrap

DICO = {'\x00': '00', '\x04': '0100', '\x08': '01000', '\x0c': '01100', 
'\x10': '010000', '\x14': '010100', '\x18': '011000', '\x1c': '011100',
' ': '0100000', '$': '0100100', '(': '0101000', ',': '0101100', '0': '0110000',
'4': '0110100', '8': '0111000', '<': '0111100', '@': '01000000',
'D': '01000100', 'H': '01001000', 'L': '01001100', 'P': '01010000',
'T': '01010100', 'X': '01011000', '\\': '01011100', '`': '01100000',
'd': '01100100', 'h': '01101000', 'l': '01101100', 'p': '01110000',
't': '01110100', 'x': '01111000', '|': '01111100', '\x03': '011',
'\x07': '0111', '\x0b': '01011', '\x0f': '01111', '\x13': '010011',
'\x17': '010111', '\x1b': '011011', '\x1f': '011111', '#': '0100011',
"'": '0100111', '+': '0101011', '/': '0101111', '3': '0110011', '7': '0110111',
';': '0111011', '?': '0111111', 'C': '01000011', 'G': '01000111',
'K': '01001011', 'O': '01001111', 'S': '01010011', 'W': '01010111',
'[': '01011011', '_': '01011111', 'c': '01100011', 'g': '01100111',
'k': '01101011', 'o': '01101111', 's': '01110011', 'w': '01110111',
'{': '01111011', '\x7f': '01111111', '\x02': '010', '\x06': '0110',
'\n': '01010', '\x0e': '01110', '\x12': '010010', '\x16': '010110',
'\x1a': '011010', '\x1e': '011110', '"': '0100010', '&': '0100110',
'*': '0101010', '.': '0101110', '2': '0110010', '6': '0110110', ':': '0111010',
'>': '0111110', 'B': '01000010', 'F': '01000110', 'J': '01001010',
'N': '01001110', 'R': '01010010', 'V': '01010110', 'Z': '01011010',
'^': '01011110', 'b': '01100010', 'f': '01100110', 'j': '01101010',
'n': '01101110', 'r': '01110010', 'v': '01110110', 'z': '01111010',
'~': '01111110', '\x01': '01', '\x05': '0101', '\t': '01001', '\r': '01101',
'\x11': '010001', '\x15': '010101', '\x19': '011001', '\x1d': '011101',
'!': '0100001', '%': '0100101', ')': '0101001', '-': '0101101',
'1': '0110001', '5': '0110101', '9': '0111001', '=': '0111101',
'A': '01000001', 'E': '01000101', 'I': '01001001', 'M': '01001101',
'Q': '01010001', 'U': '01010101', 'Y': '01011001', ']': '01011101',
'a': '01100001', 'e': '01100101', 'i': '01101001', 'm': '01101101',
'q': '01110001', 'u': '01110101', 'y': '01111001', '}': '01111101'}

def decrypt(binary):
    """Function to convert binary into string"""
    binary = wrap(binary, 8)
    ch = ''
    for b in binary:
        for i, j in DICO.items():
            if j == b:
                ch += i
    return ch

thank by advance,

like image 655
Fred Avatar asked Jan 02 '12 14:01

Fred


3 Answers

''.join([ chr(int(p, 2)) for p in wrap(binstr, 8) ])

What this does: wrap first splits your string up into chunks of 8. Then, I iterate through each one, and convert it to an integer (base 2). Each of those converted integer now get covered to a character with chr. Finally I wrap it all up with a ''.join to smash it all together.

A bit more of a breakdown of each step of the chr(int(p, 2)):

>>> int('01101010', 2)
106
>>> chr(106)
'j'

To make it fit into your pattern above:

def decrypt(binary):
    """Function to convert binary into string"""
    binary = wrap(binary, 8)
    ch = ''
    for b in binary:
        ch += chr(int(b, 2))
    return ch

or

def decrypt(binary):
    """Function to convert binary into string"""
    return ''.join([ chr(int(p, 2)) for p in wrap(binary, 8) ])

This is definitely faster since it is just doing the math in place, not iterating through the dictionary over and over. Plus, it is more readable.

like image 136
Donald Miner Avatar answered Oct 24 '22 05:10

Donald Miner


If execution speed it the most important for you, why not invert the roles of keys and values in your dict?! (If you also need the current dict, you could created an inverted version like this {v:k for k, v in DICO.items()})

Now, you find directly the searched translation by key instead of looping through the whole dict.

Your new function would look like this:

def decrypt2(binary):
    """Function to convert binary into string"""
    binary = wrap(binary, 8)
    ch = ''
    for b in binary:
        if b in DICO_INVERTED:
            ch += DICO_INVERTED[b]
    return ch

Depending on the size of your binary string, you could gain some time by changing the way you construct your output-string (see Efficient String Concatenation in Python or performance tips - string concatenation). Using join seems promising. I would give it a try: ''.join(DICO_INVERTED.get(b, '') for b in binary)

like image 33
gecco Avatar answered Oct 24 '22 07:10

gecco


did you try

def decrypt(binary):
    """Function to convert binary into string"""
    return ''.join(( chr(int(p, 2)) for p in grouper(8,binary,'') ))

where grouper is taken from here http://docs.python.org/library/itertools.html#recipes

or

def decrypt2(binary):
    """Function to convert binary into string"""
    return ''.join(( DICO_INVERTED[p] for p in grouper(8,binary,'') ))

that avoids to create temporary list

EDIT as I was choisen to be the "right" answer I have to confess that I used the other answers. The point is here not to use generator list but generator expression and iterators

like image 2
Xavier Combelle Avatar answered Oct 24 '22 07:10

Xavier Combelle