ファイルへのアクセスやソケット操作など、バイナリデータを処理するために python を使用する必要がある場合があります。このとき、Python の struct モジュールを使用して、 の 構造体 を処理できます。 C 言語 .
struct モジュールの 3 つの最も重要な 関数 は、pack()、unpack()、calcsize() です
pack(fmt, v1, v2, ...) 指定された形式 (fmt) による), put データは string (実際には C 構造体に似たバイト ストリーム) にカプセル化されます
unpack(fmt, string) 指定された形式 (fmt) に従ってバイト ストリーム文字列を解析し、解析されたタプルを返します
calcsize(fmt) 指定された形式 (fmt) が占めるメモリのバイト数を計算します
struct でサポートされている形式は次のとおりです:
Format C 型 Python バイト数
x パッドバイト 値なし 1
c 長さ 1 の char 文字列 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 整数 4
I unsigned int integer または 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
注 1.q と Q は、マシンが 64 ビット操作をサポートしている場合にのみ興味深いです
注 2。 be preceded by 数字を表す数字があります
注3. s形式は一定の長さの文字列を表し、4sは長さ4の文字列を表しますが、pはパスカル文字列を表します
注4.Pは、ポインターを変換します。その長さはマシン語の長さに関係します
注 5. 最後のポインターは、4 バイトを占めるポインターの型を表すために使用できます
C の構造体とデータを交換するには、一部の C または C++ コンパイラーが必要です32 ビット システムの場合、バイト アライメントは通常 4 バイトであるため、構造体は、フォーマットの最初の文字を使用してアライメントを変更できます。 Characterバイトの注文サイズとアラインメント'@5s6sif' のように fmt の位置を指定します
例 1:
構造は次のとおりです:
struct Header { unsigned short id; char[4] tag; unsigned int version; unsigned int count; }
socket.recv を通じて上記の構造データを受け取り、文字列 s に保存されます。 unpack() 関数を使用できます:
import struct id, tag, version, count = struct.unpack("!H4s2I", s)
データはネットワークから受信され、送信されるときはネットワーク バイト オーダーであるため、上記の形式文字列では、 ! はネットワーク バイト オーダーを使用して解析することを意味します。次の H は符号なしの短い ID を表し、4s は 4 バイトの長さを表します。2I は、符号なしの int 型データが 2 つあることを意味します
これで、情報が ID、タグ、バージョンに保存されました。 、カウント。
同様に、ローカルデータも簡単に保存できます。次に、構造体形式にパックします。
ss = struct.pack("!H4s2I", id, tag, version, count);
パック関数は、指定された形式に従って、ID、タグ、バージョン、カウントを構造体に変換します。ss は文字列になります。 c 構造体に似たバイト ストリーム)、この文字列をソケット.send(ss) を通じて送信できます。
例2:
import struct a=12.34 #将a变为二进制 bytes=struct.pack('i',a)
このとき、bytesは文字列stringであり、その文字列はバイト単位のaのバイナリ記憶内容と同じです。
次に、逆の操作を実行し、既存のバイナリ データ バイト (実際には文字列) を Python の
データ型に変換します:
#unpack はタプルを返すことに注意してください!!
a,=struct.unpack('i',bytes)
である場合、それは複数で構成されますデータは次のようになります:
a='hello' b='world!' c=2 d=45.123 bytes=struct.pack('5s6sif',a,b,c,d)
このときのバイトはバイナリ形式のデータであり、binfile.write(bytes) などのファイルに直接書き込むことができます。読み上げてください、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’来表示换行。
以上がバイナリを処理するための Python の構造体の使用方法 (パックとアンパックの使用法) についての詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。