Manchmal müssen Sie Python verwenden, um Binärdaten zu verarbeiten, z. B. beim Zugriff auf Dateien und Socket-Vorgänge. Zu diesem Zeitpunkt können Sie das Strukturmodul von Python verwenden, um Strukturen in der C-Sprache zu verarbeiten 🎜>
Die drei wichtigsten Funktionen im Strukturmodul sind pack(), unpack(), calcsize()pack(fmt, v1, v2, ...) entsprechend dem angegebenen Format ( fmt), kapseln Sie die Daten in eine Zeichenfolge (eigentlich einen Byte-Stream ähnlich einer C-Struktur) unpack(fmt, string) Analysieren Sie die Byte-Stream-Zeichenfolge gemäß dem angegebenen Format (fmt) und geben Sie das analysierte Ergebnis zurück tuplecalcsize(fmt) berechnet, wie viele Bytes Speicher das angegebene Format (fmt) belegt. Die in der Struktur unterstützten Formate sind wie folgt: Format C Type Python Anzahl der Bytesx Füllbyte kein Wert 1c Zeichenzeichenfolge der Länge 1 1b vorzeichenbehaftete Zeichenzahl Ganzzahl 1B vorzeichenlose Zeichenzahl Ganzzahl 1 ? _Bool bool 1h kurze Ganzzahl 2H vorzeichenlose kurze Ganzzahl 2i int Ganzzahl 4I ohne Vorzeichen int integer oder long 4l long integer 4L unsigned long long 4q long long long 8Q unsigned long long long 8f float float 4d double float 8s char[] string 1p char[] string 1P void * longHinweis 1. q und Q sind nur interessant, wenn die Maschine den 64-Bit-Betrieb unterstütztHinweis 2. Vor jedem Format kann eine Zahl stehen, um die Zahl anzugebenHinweis 3. Das s-Format stellt eine Zeichenfolge mit einer bestimmten Länge dar, 4s stellt eine Zeichenfolge mit der Länge 4 dar, aber p stellt eine Pascal-Zeichenfolge dar. Hinweis 4.P wird zum Konvertieren eines Zeigers in die Länge verwendet davon ist gleich dem Maschinenwort Lange Korrelation Hinweis 5. Der letzte kann zur Darstellung von Zeigertypen verwendet werden, die 4 Bytes belegen Um Daten mit der Struktur in c auszutauschen, Einige c oder c müssen ebenfalls berücksichtigt werden. Der Compiler verwendet die Byte-Ausrichtung, normalerweise in Einheiten von 4 Bytes für 32-Bit-Systeme, sodass die Struktur gemäß der Byte-Reihenfolge der lokalen Maschine konvertiert wird. Die Ausrichtung kann mithilfe des ersten Zeichens in geändert werden Format. Es ist wie folgt definiert: Reihenfolge der Zeichenbytes Größe und Ausrichtung@ native native Ausreichend 4 Bytes= nativer Standard Entsprechend der ursprünglichen Anzahl von Bytes < Little-Endian-Standard > Big-Endian-Standard-Netzwerk (= Big-Endian) Standard-Standardbytes wird an der ersten Position von fmt verwendet, wie „@5s6sif“ Beispiel 1: Die Struktur ist wie folgt:
Das Obige Strukturdaten werden über socket.recv empfangen und im String s gespeichert. Jetzt können Sie die Funktion unpack() verwenden:
struct Header { unsigned short id; char[4] tag; unsigned int version; unsigned int count; }
Im obigen Format string ,! zeigt an, dass wir zum Parsen die Netzwerk-Byte-Reihenfolge verwenden müssen, da unsere Daten vom Netzwerk empfangen werden und bei der Übertragung im Netzwerk in der Netzwerk-Byte-Reihenfolge vorliegen. Das folgende H steht für eine vorzeichenlose Kurz-ID und 4s steht für A 4-. Byte lange Zeichenfolge, 2I bedeutet, dass es zwei vorzeichenlose int-Daten gibt.
import struct id, tag, version, count = struct.unpack("!H4s2I", s)
Die Pack-Funktion konvertiert ID, Tag, Version und Anzahl in Struktur. Header ist jetzt ein String (eigentlich ein Byte-Stream ähnlich einem c Struktur) und diese Zeichenfolge kann über socket.send(ss) gesendet werden.
Beispiel 2:
ss = struct.pack("!H4s2I", id, tag, version, count);
Zu diesem Zeitpunkt handelt es sich bei Bytes um eine Zeichenfolge, und die Zeichenfolge entspricht dem binären Speicherinhalt von a in Bytes.
Führen Sie dann den umgekehrten Vorgang aus und konvertieren Sie die vorhandenen Binärdatenbytes (eigentlich eine Zeichenfolge) in den Python-Datentyp:
import struct a=12.34 #将a变为二进制 bytes=struct.pack('i',a)
a,=struct.unpack('i',bytes)
Die Bytes sind zu diesem Zeitpunkt in binärer Form. Die Daten kann direkt in eine Datei wie binfile.write(bytes)
geschrieben werden. Wenn wir es dann brauchen, können wir es auslesen, bytes=binfile.read()
a='hello' b='world!' c=2 d=45.123 bytes=struct.pack('5s6sif',a,b,c,d)
'5s6sif' heißt fmt, was eine formatierte Zeichenfolge ist, die aus Zahlen und Zeichen besteht, 2i bedeutet 2 ganze Zahlen usw. Im Folgenden sind die verfügbaren Zeichen und Typen aufgeführt. ctype bedeutet, dass sie den Typen in Python eins zu eins entsprechen können.
Hinweis: Bei der Verarbeitung von Binärdateien sind Probleme aufgetreten
a,b,c,d=struct.unpack('5s6sif',bytes)
Dann binfile=open( Was ist der Unterschied zwischen den Ergebnissen von Dateipfad,'r')?
Es gibt zwei Unterschiede:
Erstens: Wenn Sie bei der Verwendung von „r“ auf „0x1A“ stoßen, wird dies als das Ende der Datei betrachtet, also EOF. Bei Verwendung von „rb“ tritt dieses Problem nicht auf. Das heißt, wenn Sie im Binärformat schreiben und im Text auslesen, wird nur ein Teil der Datei ausgelesen, wenn „0X1A“ vorhanden ist. Bei Verwendung von „rb“ wird bis zum Ende der Datei gelesen.
Zweitens können wir für die Zeichenfolge x=’abcndef’ len(x) verwenden, um ihre Länge auf 7 zu bringen. Wir nennen n das Zeilenumbruchzeichen, das eigentlich „0X0A“ ist. Wenn wir im Textmodus „w“ schreiben, wird „0X0A“ auf der Windows-Plattform automatisch in zwei Zeichen „0X0D“, „0X0A“ geändert, dh die Dateilänge beträgt tatsächlich 8. Beim Lesen im Textmodus „r“ wird es automatisch in das ursprüngliche Zeilenumbruchzeichen konvertiert. Wenn Sie zum Schreiben in den Binärmodus „wb“ wechseln, bleibt ein Zeichen unverändert und wird beim Lesen so gelesen, wie es ist. Wenn Sie also im Textmodus schreiben und im Binärmodus lesen, müssen Sie dieses zusätzliche Byte berücksichtigen. „0X0D“ wird auch Wagenrücklaufzeichen genannt. Unter Linux wird sich das nicht ändern. Weil Linux nur „0X0A“ zur Darstellung von Zeilenumbrüchen verwendet.