Heim >Backend-Entwicklung >Python-Tutorial >Detaillierte Erläuterung der Python-Methode zur Verwendung von struct zur Verarbeitung von Binärdaten

Detaillierte Erläuterung der Python-Methode zur Verwendung von struct zur Verarbeitung von Binärdaten

巴扎黑
巴扎黑Original
2017-09-13 10:05:342015Durchsuche

Dieser Artikel stellt hauptsächlich relevante Informationen über die Verwendung von Strukturen zur Verarbeitung binärer Beispiele vor. Ich hoffe, dass jeder, der diesen Artikel benötigt, auf

Pythons zurückgreifen kann Verwendung von Struktur zum Verarbeiten Detaillierte Erläuterung von Binärbeispielen

Manchmal müssen Sie Python verwenden, um Binärdaten zu verarbeiten, beispielsweise beim Zugriff auf Dateien und Socket-Vorgänge. Zu diesem Zeitpunkt können Sie das Strukturmodul von Python verwenden Um es zu vervollständigen, können Sie Struktur in der Sprache C verwenden.

  • Die drei wichtigsten Funktionen im Strukturmodul sind pack(), unpack(), calcsize()

  • pack(fmt, v1, v2, ...) Packen Sie die Daten entsprechend dem angegebenen Format (fmt) in einen String (eigentlich ein Bytestream ähnlich einer C-Struktur). )

  • unpack(fmt, string) Analysiert die Byte-Stream-Zeichenfolge gemäß dem angegebenen Format (fmt) und gibt das analysierte Tupel zurück

  • calcsize (fmt) Berechnung Wie viele Bytes Speicher belegt ein bestimmtes Format (fmt)

Die unterstützten Formate in struct sind wie folgt:

tr> tr> tr>8 tr>
Format C-Typ Python Bytes
x Pad-Byte kein Wert 1
c char String der Länge 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
iint integer 4
I unsigned int Ganzzahl oder Long 4
l Long Ganzzahl 4
L unsigned long long 4
q long long long 8
Qunsigned long long long 8
f float td> float 4
d double float
s char[] string 1
p char[] string 1
P void * long
Format C Type Python 字节数
x pad byte no value 1
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer or long 4
l long integer 4
L unsigned long long 4
q long long long 8
Q unsigned long long long 8
f float float 4
d double float 8
s char[] string 1
p char[] string 1
P void * long

Hinweis 1.q und Q sind nur in Es ist interessant, wenn die Maschine den 64-Bit-Betrieb unterstützt
Hinweis 2. Vor jedem Format kann eine Zahl stehen, die die Zahl angibt
Hinweis 3. Das s-Format stellt eine Zeichenfolge einer bestimmten Länge dar. und 4s stellt eine Zeichenfolge der Länge 4 dar, aber p stellt eine Pascal-Zeichenfolge dar
Hinweis 4. P wird zum Konvertieren eines Zeigers verwendet, seine Länge hängt von der Länge des Maschinenworts ab
Hinweis 5. Letzteres kann verwendet werden um den Zeigertyp darzustellen, der 4 Bytes belegt

Um Daten mit Strukturen in C auszutauschen, muss auch berücksichtigt werden, dass einige C- oder C++-Compiler die Byteausrichtung verwenden, normalerweise basierend auf 32-Bit-Systemen auf 4 Bytes, daher basiert die Struktur auf der Konvertierung der nativen Maschinenbyte-Reihenfolge. Sie können das erste Zeichen im Format verwenden, um die Ausrichtung wie folgt zu ändern:

Zeichen@Netzwerk (= Big-Endian)
Byte-Reihenfolge Größe und Ausrichtung
native native Ergibt 4 Bytes
= native standard Drücken Sie das ursprüngliche Wort Anzahl der Abschnitte
dcf16330690b81abbfbeac1327ae166c Big-Endian Standard    Entsprechend der ursprünglichen Anzahl von Bytes
!
Character Byte order Size and alignment
@ native native            凑够4个字节
= native standard        按原字节数
75a803047e7211490f6fad78c07d3c08 big-endian standard       按原字节数
! network (= big-endian)

standard       按原字节数

Standard Basierend auf der ursprünglichen Anzahl von Bytes

Die Verwendungsmethode besteht darin, es an die erste Position von fmt zu setzen, wie „@5s6sif“

Beispiel 1:

Beispielsweise hat eine Struktur


struct Header
{
  unsigned short id;
  char[4] tag;
  unsigned int version;
  unsigned int count;
}

die oben genannten Strukturdaten über socket.recv erhalten, die in der Zeichenfolge s gespeichert sind. Jetzt müssen sie analysiert werden out. Sie können die Funktion unpack() verwenden.


import struct id, tag, version, count = struct.unpack("!H4s2I", s)
In der obigen Formatzeichenfolge gibt ! an, dass wir die Netzwerk-Byte-Reihenfolge verwenden möchten Unsere Daten werden vom Netzwerk empfangen und in der Netzwerk-Byte-Reihenfolge angezeigt. Das folgende H steht für eine vorzeichenlose Kurz-ID, 4s steht für eine 4-Byte-lange Zeichenfolge und 2I steht für zwei vorzeichenlose Int-Daten.

Bestehen Sie einfach einen Entpackvorgang, und jetzt wurden unsere Informationen in ID, Tag, Version und Anzahl gespeichert.


In ähnlicher Weise können auch lokale Daten einfach gespeichert und dann in das Strukturformat gepackt werden .



ss = struct.pack("!H4s2I", id, tag, version, count);
Die Pack-Funktion konvertiert ID, Tag, Version, Anzahl in Struktur Header, SS gemäß dem angegebenen Format. Jetzt ist es eine Zeichenfolge (eigentlich). ein Byte-Stream ähnlich einer C-Struktur).

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

vorhandene Binärdatenbytes (eigentlich eine Zeichenfolge) und konvertieren Sie sie zurück in den Python-Datentyp:

import struct
a=12.34
#将a变为二进制
bytes=struct.pack('i',a)


Beachten Sie, dass das Entpacken ein Tupel zurückgibt


, wenn also nur eine Variable vorhanden ist:


a,=struct.unpack('i',bytes)


Dann müssen Sie dies beim Dekodieren tun



Wenn Sie direkt a=struct.unpack('i',bytes ), dann ist a=(12.34,) ein Tupel anstelle der ursprünglichen Gleitkommazahl.
bytes=struct.pack('i',a)

Wenn es aus mehreren Daten besteht, kann es so aussehen:


a,=struct.unpack('i',bytes) 或者 (a,)=struct.unpack('i',bytes)

Die Bytes sind zu diesem Zeitpunkt binäre Daten Formular. Wir können direkt in eine Datei wie binfile.write(bytes)


schreiben und sie dann auslesen, wenn wir sie brauchen, bytes=binfile.read()


und dann übergeben struct.unpack() wird in eine Python-Variable dekodiert

a='hello'
b='world!'
c=2
d=45.123
bytes=struct.pack('5s6sif',a,b,c,d)



'5s6sif' Dies wird als fmt bezeichnet, eine Formatzeichenfolge , bestehend aus Zahlen und Zeichen, 5s Stellt eine Zeichenfolge mit 5 Zeichen dar, 2i, stellt 2 Ganzzahlen usw. dar. Im Folgenden sind die verfügbaren Zeichen und Typen aufgeführt. ctype gibt an, dass sie den Typen in Python eins zu eins entsprechen können.


Hinweis: Bei der Verarbeitung von Binärdateien sind Probleme aufgetreten


Wenn wir Binärdateien verarbeiten, müssen wir die folgenden Methoden verwenden
a,b,c,d=struct.unpack('5s6sif',bytes)

Was ist also der Unterschied zum Ergebnis von binfile=open(filepath,'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 dieser 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.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Python-Methode zur Verwendung von struct zur Verarbeitung von Binärdaten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn