Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Einführung in Pythons Verwendung von struct zur Verarbeitung von Binärdateien (Verwendung beim Packen und Entpacken)

Detaillierte Einführung in Pythons Verwendung von struct zur Verarbeitung von Binärdateien (Verwendung beim Packen und Entpacken)

高洛峰
高洛峰Original
2017-03-19 14:49:492055Durchsuche

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 verarbeiten c Die -Struktur in der Sprache . Die drei wichtigsten

-Funktionen

im struct-Modul sind pack(), unpack(), calcsize ()

pack(fmt, v1, v2, ...) Packen Sie die Daten gemäß dem angegebenen Format (fmt) in einen String (eigentlich einen Bytestrom ähnlich einer C-Struktur). )

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

calcsize(fmt) Berechnen Sie, wie Wie viele Bytes Speicher belegt ein bestimmtes Format (fmt)?

Die unterstützten Formate in struct sind wie folgt:

Fürmat C Type Python Anzahl der Bytes

x Füllbyte kein Wert 1

c Zeichenkette der Länge 1 1

b vorzeichenbehaftetes Zeichen Ganzzahl 1

B vorzeichenloses Zeichen Ganzzahl 1

? _Bool bool 1

h kurze Ganzzahl 2

H vorzeichenlose kurze Ganzzahl 2

i int Ganzzahl 4

I ohne Vorzeichen int integer oder 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 interessant, wenn die Maschine den 64-Bit-Betrieb unterstützt

Hinweis 2. Vor jedem Format kann eine Zahl stehen um die Zahl anzugeben

Hinweis 3. Das s-Format stellt eine Zeichenfolge einer bestimmten Länge dar, 4s stellt eine Zeichenfolge der Länge 4 dar, aber p stellt eine Pascal-Zeichenfolge dar

Hinweis 4.P wird verwendet Um einen Zeiger zu konvertieren, hängt seine Länge von der Länge des Maschinenworts ab

Hinweis 5. Der letzte kann zur Darstellung von Zeigertypen verwendet werden und belegt 4 Bytes

Um Daten mit dem auszutauschen Struktur in c müssen wir auch berücksichtigen. Einige C- oder C++-Compiler verwenden die Byte-Ausrichtung, normalerweise 4 Bytes für 32-Bit-Systeme, sodass die Struktur entsprechend der Byte-Reihenfolge des lokalen Computers konvertiert wird. Sie können das erste Zeichen im Format zum Ändern verwenden die Ausrichtung. .Die Definition lautet wie folgt:

Reihenfolge der Zeichenbytes Größe und Ausrichtung

@ native native Bilden Sie 4 Bytes aus

= nativer Standard Entsprechend der ursprünglichen Anzahl von Bytes

< Little-Endian-Standard basierend auf der ursprünglichen Anzahl von Bytes

> Big-Endian-Standard basierend auf der ursprünglichen Anzahl von Bytes

! -endian)

Standard Entsprechend der ursprünglichen Anzahl von Bytes wird

verwendet, indem es an der ersten Position von fmt platziert wird, genau wie '@5s6sif'

Beispiel 1:

Die Struktur ist wie folgt:

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

Die obigen Strukturdaten wurden über socket.recv empfangen und müssen nun analysiert werden Verwenden Sie die Funktion unpack():

import struct
id, tag, version, count = struct.unpack("!H4s2I", s)

Oben In der Formatzeichenfolge gibt ! an, dass wir zum Parsen die Netzwerk-Byte-Reihenfolge verwenden müssen, da unsere Daten vom Netzwerk empfangen werden und in der Netzwerk-Byte-Reihenfolge vorliegen Das folgende H stellt eine vorzeichenlose kurze For-ID dar, 4s stellt eine 4 Byte lange Zeichenfolge dar und 2I stellt zwei vorzeichenlose int-Typdaten dar.

Übergeben Sie einfach ein Entpacken, und jetzt sind unsere Informationen gespeichert in ID, Tag, Version und Anzahl.

Ähnlich können Sie auch lokale Daten einfach in das Strukturformat packen:

ss = struct.pack("!H4s2I", id, tag, version, count);

Die Pack-Funktion konvertiert ID, Tag, Version, Zählen Sie gemäß dem angegebenen Format in das Strukturformat. Ohne den Struktur-Header ist ss jetzt ein String (eigentlich ein Byte-Stream ähnlich einer C-Struktur), und dieser String kann über socket.send(ss) gesendet werden.

Beispiel 2:

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

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ären Datenbytes (eigentlich eine Zeichenfolge) in den -Datentyp von Python :

#Hinweis: Unpack gibt ein Tupel zurück!!

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

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

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

Die Bytes sind zu diesem Zeitpunkt Daten in Binärform, die direkt in eine Datei geschrieben werden können wie zum Beispiel binfile.write(bytes)

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

再通过struct.unpack()解码成python变量:

a,b,c,d=struct.unpack('5s6sif',bytes)

’5s6sif’这个叫做fmt,就是格式化字符串,由数字加字符构成,5s表示占5个字符的字符串,2i,表示2个整数等等,下面是可用的字符及类型,ctype表示可以与python中的类型一一对应。

注意:二进制文件处理时会碰到的问题

我们使用处理二进制文件时,需要用如下方法:

binfile=open(filepath,'rb')    
#读二进制文件
binfile=open(filepath,'wb')   
#写二进制文件

那么和binfile=open(filepath,’r')的结果到底有何不同呢?

不同之处有两个地方:

第一,使用’r'的时候如果碰到’0x1A’,就会视为文件结束,这就是EOF。使用’rb’则不存在这个问题。即,如果你用二进制写入再用文本读出的话,如果其中存在’0X1A’,就只会读出文件的一部分。使用’rb’的时候会一直读到文件末尾。

第二,对于字符串x=’abc\ndef’,我们可用len(x)得到它的长度为7,\n我们称之为换行符,实际上是’0X0A’。当我们用’w'即文本方式写的时候,在windows平台上会自动将’0X0A’变成两个字符’0X0D’,’0X0A’,即文件长度实际上变成8.。当用’r'文本方式读取时,又自动的转换成原来的换行符。如果换成’wb’二进制方式来写的话,则会保持一个字符不变,读取时也是原样读取。所以如果用文本方式写入,用二进制方式读取的话,就要考虑这多出的一个字节了。’0X0D’又称回车符。linux下不会变。因为linux只使用’0X0A’来表示换行。

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in Pythons Verwendung von struct zur Verarbeitung von Binärdateien (Verwendung beim Packen und Entpacken). 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