ホームページ  >  記事  >  バックエンド開発  >  バイナリを処理するための Python の構造体の使用方法 (パックとアンパックの使用法) についての詳細な紹介

バイナリを処理するための Python の構造体の使用方法 (パックとアンパックの使用法) についての詳細な紹介

高洛峰
高洛峰オリジナル
2017-03-19 14:49:492054ブラウズ

ファイルへのアクセスやソケット操作など、バイナリデータを処理するために 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。