structモジュールでバイナリデータを処理する



ファイルへのアクセス、socket操作など、pythonでバイナリデータを処理する必要がある場合がある.この場合、pythonのstructモジュールを用いる完成することができる.c言語の構造体をstructで処理することができる.
structモジュールで最も重要な3つの関数はpack(),unpack(),calcsize()である.
pack(fmt, v1, v2, ...)           (fmt),         (       c       )
unpack(fmt, string) (fmt) string, tuple
calcsize(fmt) (fmt)

structでサポートされているフォーマットは次の表のとおりです.
>フォーマット
cタイプ
pythonタイプ
> x
char
なし(パディングバイトを表す)
> c
char
長さ1の文字列
> b
signed char
integer
> B
unsigned char
integer
> h
short
integer
> H
unsigned short
integer
> i
int
integer
> I
unsigned int
long
> l
long
integer
> L
unsigned long
long
> q
long long
long
> Q
unsigned long long
long
> f
float
float
> d
double
float
> s
char[]
string
> p
char[]
string
> P
void*
integer
注1.qとQは、機器が64ビットの操作をサポートする場合のみ興味深い注2.各フォーマットの前に1つの数字があり、個数注3を表すことができる.sフォーマットは一定の長さの文字列を表し、4 sは長さ4の文字列を表すが、pはpascal文字列注4を表す.Pはポインタを変換するために使用され、その長さは機械の文字長に関連する.
デフォルトではstructはローカルマシンのバイト順に変換する.ただし、フォーマットの最初の文字で位置合わせを変更することができる.次のように定義します.
>文字
バイト順
長さと配置
> @
native
native
> =
native
standard
> <
little-endian
standard
>>
big-endian
standard
> !
network (= big-endian)
standard
structがあれば、バイナリデータを簡単に操作できます.
たとえば、構造体があります.
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は1つのunsigned shortのid、4 sは4バイト長の文字列、2 Iは2つのunsigned intタイプのデータを表す.
unpackを通じて、今id、tag、version、countに私たちの情報を保存しました.
同様に、ローカルデータをstruct形式に再packすることも容易である.
ss = struct.pack("!H4s2I", id, tag, version, count);

pack関数はid,tag,version,countを指定したフォーマットで構造体Headerに変換し、ssは現在文字列(実際にはc構造体に似たバイトストリーム)であり、socket.send(ss)はこの文字列を送信します.