Конвертировать двоичные файлы в ASCII и наоборот - PullRequest
66 голосов
/ 13 сентября 2011

Используя этот код, чтобы взять строку и преобразовать ее в двоичный файл:

bin(reduce(lambda x, y: 256*x+y, (ord(c) for c in 'hello'), 0))

это выводит:

0b110100001100101011011000110110001101111

Который, если я помещу его на этот сайт (на правом сайте), я получу обратно сообщение hello. Мне интересно, какой метод он использует. Я знаю, что мог бы разделить строку двоичного файла на 8, а затем сопоставить ее с соответствующим значением bin(ord(character)) или каким-либо другим способом. Действительно ищу что-то попроще.

Ответы [ 7 ]

139 голосов
/ 13 сентября 2011

Для символов ASCII в диапазоне [ -~] на Python 2:

>>> import binascii
>>> bin(int(binascii.hexlify('hello'), 16))
'0b110100001100101011011000110110001101111'

В обратном порядке:

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> binascii.unhexlify('%x' % n)
'hello'

В Python 3.2 +:

>>> bin(int.from_bytes('hello'.encode(), 'big'))
'0b110100001100101011011000110110001101111'

В обратном порядке:

>>> n = int('0b110100001100101011011000110110001101111', 2)
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big').decode()
'hello'

Для поддержки всех символов Юникода в 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'

Вот версия с одним исходным кодом, совместимая с Python 2/3:

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)))
* * Пример тысяча двадцать-одина * * тысяча двадцать-дв
>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True
13 голосов
/ 03 декабря 2016

Встроенный только python

Вот чистый метод python для простых строк, оставленный здесь для потомков.

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!
9 голосов
/ 13 сентября 2011

Я не уверен, как вы думаете, что вы можете сделать это, кроме посимвольных символов - это по своей сути посимвольная операция.Конечно, есть код, который сделает это за вас, но нет более простого способа, чем сделать это посимвольно.

Во-первых, вам нужно убрать префикс 0b, а слева -Обнуляйте строку, чтобы ее длина делилась на 8, чтобы было проще разделить цепочку битов на символы:

bitstring = bitstring[2:]
bitstring = -len(bitstring) % 8 * '0' + bitstring

Затем вы разделяете строку на блоки из восьми двоичных цифр, конвертируя их в символы ASCIIи соедините их обратно в строку:

string_blocks = (bitstring[i:i+8] for i in range(0, len(bitstring), 8))
string = ''.join(chr(int(char, 2)) for char in string_blocks)

Если вы действительно хотите рассматривать его как число, вам все равно придется учитывать тот факт, что самый левый символ будет иметь длину не более семи цифр, если выхочу идти слева направо, а не справа налево.

2 голосов
/ 27 мая 2013

Это мой способ решить вашу задачу:

str = "0b110100001100101011011000110110001101111"
str = "0" + str[2:]
message = ""
while str != "":
    i = chr(int(str[:8], 2))
    message = message + i
    str = str[8:]
print message
1 голос
/ 03 сентября 2015

Если вы не хотите импортировать какие-либо файлы, вы можете использовать это:

with open("Test1.txt", "r") as File1:
St = (' '.join(format(ord(x), 'b') for x in File1.read()))
StrList = St.split(" ")

, чтобы преобразовать текстовый файл в двоичный файл.

, и вы можете использовать это, чтобы преобразовать его обратнов строку:

StrOrgList = StrOrgMsg.split(" ")


for StrValue in StrOrgList:
    if(StrValue != ""):
        StrMsg += chr(int(str(StrValue),2))
print(StrMsg)

надеюсь, что это полезно, я использовал это с некоторым пользовательским шифрованием для отправки по TCP.

1 голос
/ 13 сентября 2011

Вы ищете код для этого или понимаете алгоритм?

Это делает то, что вам нужно ? В частности a2b_uu и b2a_uu? Есть много других вариантов на случай, если это не то, что вы хотите.

(ПРИМЕЧАНИЕ: не парень из Python, но это казалось очевидным ответом)

0 голосов
/ 21 августа 2014

Это улучшенная версия JF Sebastian's.Спасибо за фрагменты, хотя JF Себастьян.

import binascii, sys
def goodbye():
    sys.exit("\n"+"*"*43+"\n\nGood Bye! Come use again!\n\n"+"*"*43+"")
while __name__=='__main__':
    print "[A]scii to Binary, [B]inary to Ascii, or [E]xit:"
    var1=raw_input('>>> ')
    if var1=='a':
        string=raw_input('String to convert:\n>>> ')
        convert=bin(int(binascii.hexlify(string), 16))
        i=2
        truebin=[]
        while i!=len(convert):
            truebin.append(convert[i])
            i=i+1
        convert=''.join(truebin)
        print '\n'+'*'*84+'\n\n'+convert+'\n\n'+'*'*84+'\n'
    if var1=='b':
        binary=raw_input('Binary to convert:\n>>> ')
        n = int(binary, 2)
        done=binascii.unhexlify('%x' % n)
        print '\n'+'*'*84+'\n\n'+done+'\n\n'+'*'*84+'\n'
    if var1=='e':
        aus=raw_input('Are you sure? (y/n)\n>>> ')
        if aus=='y':
            goodbye()
...