Konvertieren Sie Binärdateien in ASCII und umgekehrt


82

Verwenden Sie diesen Code, um eine Zeichenfolge in eine Binärdatei zu konvertieren:

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

dies gibt aus:

0b110100001100101011011000110110001101111

Wenn ich es in diese Site (auf der rechten Seite) stelle, bekomme ich meine Nachricht hellozurück. Ich frage mich, welche Methode es verwendet. Ich weiß, ich könnte die Binärzeichenfolge in Achtel aufteilen und sie dann mit dem entsprechenden Wert auf bin(ord(character))oder auf andere Weise abgleichen. Wirklich auf der Suche nach etwas Einfacherem.


1
Ist Ihre Frage also: "Gibt es eine prägnantere Möglichkeit, die Umkehrung meines Codes durchzuführen als die offensichtliche?"
Tripleee

1
related: Die b2a_binErweiterung in Cython ermöglicht das Erstellen von binären Zeichenfolgen ( "01") direkt aus Bytestrings, ohne eine Python-Zwischenzahl zu erstellen .
JFS

Antworten:


157

Für ASCII-Zeichen im Bereich [ -~]von Python 2:

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

Rückwärts:

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

In Python 3.2+:

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

Rückwärts:

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

So unterstützen Sie alle Unicode-Zeichen 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'

Hier ist eine Python 2/3-kompatible Version aus einer Hand:

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

Beispiel

>>> text_to_bits('hello')
'0110100001100101011011000110110001101111'
>>> text_from_bits('110100001100101011011000110110001101111') == u'hello'
True

3
@JFSebastian Ich habe diese Methode mit der aktuellen Python-Version ausprobiert und es scheint, dass es nicht funktioniert. <br/> TypeError: 'str' unterstützt die Pufferschnittstelle nicht <br/> Würden Sie Ihre Antwort aktualisieren
hamza

3
@hamza: Es funktioniert unter Python 2. Unter Python 3 sollten Sie zuerst str in Bytes konvertieren, z. B.your_string.encode('ascii', 'strict')
jfs

1
@JFSebasitian: Danke, aber als ich es umgekehrt versuchte, gab die unhexlify-Funktion eine Fehlermeldung zurück: binascii.Error: String mit ungerader Länge.
Hamza

3
@hamza: Stellen Sie es voran, '0'wenn die Länge der Hex-Zeichenfolge nicht gerade ist. Es passiert, wenn das erste Zeichen in der ursprünglichen Zeichenfolge einen ASCII-Code von weniger als 16 hat, z . B. '\n'oder '\t'. Bei ASCII-Buchstaben kommt es nie zu einer ungeraden Länge [ -~].
JFS

22

Nur eingebautpython

Hier ist eine reine Python-Methode für einfache Zeichenfolgen, die hier für die Nachwelt verbleibt.

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!

2
chr (int ()) ist das, wonach ich gesucht habe!
JqueryToAddNumbers

Genau das, wonach ich gesucht habe !!
Joachim

9

Ich bin mir nicht sicher, wie Sie es anders als zeichenweise machen können - es ist von Natur aus eine zeichenweise Operation. Es gibt sicherlich Code, der dies für Sie erledigt, aber es gibt keinen "einfacheren" Weg, als dies Zeichen für Zeichen zu tun.

Zuerst müssen Sie das 0bPräfix entfernen und die Zeichenfolge mit dem linken Nullpunkt auffüllen, damit ihre Länge durch 8 teilbar ist, um die Aufteilung der Bitfolge in Zeichen zu vereinfachen:

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

Dann teilen Sie die Zeichenfolge in Blöcke mit acht Binärziffern auf, konvertieren sie in ASCII-Zeichen und verbinden sie wieder zu einer Zeichenfolge:

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)

Wenn Sie es tatsächlich als Zahl behandeln möchten, müssen Sie dennoch berücksichtigen, dass das Zeichen ganz links höchstens sieben Stellen lang ist, wenn Sie von links nach rechts statt von rechts nach links gehen möchten.


2

Dies ist mein Weg, um Ihre Aufgabe zu lösen:

str = "0b110100001100101011011000110110001101111"
str = "0" + str[2:]
message = ""
while str != "":
    i = chr(int(str[:8], 2))
    message = message + i
    str = str[8:]
print message

Warum fügen Sie '0' bei str = "0" + str [2:] hinzu? 0b wird benötigt, um hier zu entfernen, da es beginnt.
Bimlesh Sharma

2

Wenn Sie keine Dateien importieren möchten, können Sie Folgendes verwenden:

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

um eine Textdatei in eine Binärdatei zu konvertieren.

und Sie können dies verwenden, um es wieder in einen String zu konvertieren:

StrOrgList = StrOrgMsg.split(" ")


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

Ich hoffe, das ist hilfreich. Ich habe dies mit einer benutzerdefinierten Verschlüsselung verwendet, um über TCP zu senden.


1

Suchen Sie den Code dafür oder verstehen Sie den Algorithmus?

Tut das was du brauchst ? Speziell a2b_uuund b2a_uu? Es gibt viele andere Optionen für den Fall, dass diese nicht das sind, was Sie wollen.

(HINWEIS: Kein Python-Typ, aber dies schien eine offensichtliche Antwort zu sein)


Ich habe ein bisschen nachgeforscht, binascii funktioniert nicht für mich und sucht hauptsächlich nach dem Code. Wenn ich ihn sehen kann, kann ich ihn verstehen. Vielen Dank, obwohl EDIT: Wenn ich ASCII mit binascii a2b_uu für "h" in Binär konvertiere, ist \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00, was nicht das ist, was ich brauche, ich brauche 'Hallo' und tatsächliche Einsen und Nullen nicht Shellcode suchen ASCII, auch es funktioniert nur char von char
sbrichards

@Jaxidian das war sehr hilfreich für meine Zwecke. Jemand hat einige Daten in einer Zeichenfolge gespeichert und ich habe sie. Ich bin mir ziemlich sicher, dass es sich um ein 64-Binär-B / C der Polsterung handelt. Ich kann das erfolgreich anwenden b2a_base64, aber das Ergebnis ist in der Tat bestenfalls verwirrend. Wie bekomme ich von dort eine Liste von Boolleans / Integer (0,1)?
Ufos

0

Konvertieren Sie Binärdateien in äquivalente Zeichen.

k=7
dec=0
new=[]
item=[x for x in input("Enter 8bit binary number with , seprator").split(",")]
for i in item:
    for j in i:
        if(j=="1"):
            dec=2**k+dec
            k=k-1
        else:
            k=k-1
    new.append(dec)
    dec=0
    k=7
print(new)
for i in new:
    print(chr(i),end="")

-1

Dies ist eine überarbeitete Version von JF Sebastian. Danke für die Schnipsel, obwohl JF Sebastian.

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()
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.