For ASCII characters in the range [ -~] on Python 2:
>>> import binascii
>>> bin(int(binascii.hexlify('hello'), 16))
'0b110100001100101011011000110110001101111'
In reverse:
>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> binascii.unhexlify('%x' % n)
'hello'
In Python 3.2+:
>>> bin(int.from_bytes('hello'.encode(), 'big'))
'0b110100001100101011011000110110001101111'
In reverse:
>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()
'hello'
To support all Unicode characters in Python 3:
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
Here's single-source Python 2/3 compatible version:
import binascii
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return int2bytes(n).decode(encoding, errors)
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
Example
>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True
Answer from jfs on Stack OverflowFor ASCII characters in the range [ -~] on Python 2:
>>> import binascii
>>> bin(int(binascii.hexlify('hello'), 16))
'0b110100001100101011011000110110001101111'
In reverse:
>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> binascii.unhexlify('%x' % n)
'hello'
In Python 3.2+:
>>> bin(int.from_bytes('hello'.encode(), 'big'))
'0b110100001100101011011000110110001101111'
In reverse:
>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()
'hello'
To support all Unicode characters in Python 3:
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
Here's single-source Python 2/3 compatible version:
import binascii
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
return bits.zfill(8 * ((len(bits) + 7) // 8))
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return int2bytes(n).decode(encoding, errors)
def int2bytes(i):
hex_string = '%x' % i
n = len(hex_string)
return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
Example
>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True
Built-in only python
Here is a pure python method for simple strings, left here for posterity.
def string2bits(s=''):
return [bin(ord(x))[2:].zfill(8) for x in s]
def bits2string(b=None):
return ''.join([chr(int(x, 2)) for x in b])
s = 'Hello, World!'
b = string2bits(s)
s2 = bits2string(b)
print 'String:'
print s
print '\nList of Bits:'
for x in b:
print x
print '\nString:'
print s2
String:
Hello, World!
List of Bits:
01001000
01100101
01101100
01101100
01101111
00101100
00100000
01010111
01101111
01110010
01101100
01100100
00100001
String:
Hello, World!
Python Binary string to ASCII text - Stack Overflow
How to convert binary string to ascii string in python? - Stack Overflow
How to convert bytes to string in python?
7-bit ASCII encoding in Python?
Note : This is a spoiler for the challenge in r/Dailyprogrammer this week so if you partake in that reddit beware!
Anyway, I was trying to work out how to change a string consisting of binary digits into a string of ascii characters. Some googling suggested a module that would work "binascii". Initially I was using the code binascii.b2a_uu(data) to convert, but this only works for 45 bytes or less. Some more googling led me to this code which works perfectly...
string = int("your binary here", 2) print binascii.unhexlify("%x" % string)
My problem is that I don't feel I understand why this works. Knowing that it does work is not good enough for me. I get that int("some binary",2) specifies an integer that is in base 2. What I don't understand is:
-
Why does unhexlify turn binary into ascii? Hexadecmial doesn't come into it surely?
-
What do the %x and % symbols mean? I think they must mean "everything"? But I am not sure.
Using this code with the following input:
"0110100001100101011011000110110001101111"
gives the output
"hello"
See String Formatting for what "%x" % string is doing.
Spoiler: It's where the hex comes from.
This is a pretty indirect way to solve the problem. u/diesch explains why you're doing hex stuff.
Here's some code that might make it clearer how binary ascii conversion actually works:
binary = "0110100001100101011011000110110001101111"
byte_strings = [int(binary[n:n+8], 2) for n in range(0, len(binary), 8)]
string = "".join(map(chr, bytes))
Basically, each character is a byte (8 bits). Split the string into byte strings, convert those to bytes (instead of strings) and then use chr to convert the ints to characters.
No hex or libraries involved!
Let's take the word 'hello' which is 0110100001100101011011000110110001101111
To translate that back to characters we can use chr and int (with a base of 2) and some list slicing...
''.join(chr(int(bin_text[i:i+8], 2)) for i in xrange(0, len(bin_text), 8))
If we wanted to take 'hello' and convert it to binary we can use ord and string formatting...
''.join('{:08b}'.format(ord(c)) for c in 'hello')
Maybe you can use built-in functions:
>>> myString = "hello"
>>> ba = bytearray(myString)
>>> ba[0]
104
>>> bin(ba[0])
'0b1101000'
Split the 0b:
>>> bin(ba[0]).split('b')[1]
'1101000'
or
>>> bin(ba[0])[2:]
'1101000'
I'll hope you can solve your problem with the snippets! :)