はじめに
本記事ではPytohnでバイナリデータを扱う際に使えるstructライブラリの基本的な使い方を解説する。
このライブラリにはバイナリデータに変換、またはその逆の変換をする関数などが提供されている。
structライブラリはPythonの標準ライブラリなので、以下のように読み込めば使える。
from struct import *
structライブラリの関数
pack関数
任意のデータをバイト列オブジェクトにしたものを返す関数。
struct.pack(format, v1, v2, .....)
v1, v2にはバイト列オブジェクトに変換したいデータが、formatにはv1, v2のフォーマット文字がそれぞれ入る。
unpack関数
バイナリデータを指定されたフォーマットに従って、元のデータに戻す関数。
struct.unpack(format, buffer)
bufferには変換したいバイト列オブジェクトが、formatにはbufferの元のデータのフォーマット文字がそれぞれ入る。
フォーマット文字
pack, unpackのformatには、以下のフォーマット文字が入る。
フォーマット文字 | Cの型 | Pythonの型 | 標準サイズ(byte) |
---|---|---|---|
"c" | char | 長さ1のバイト列 | 1 |
"b" | signed char(符号付き整数) | 整数 | 1 |
"B" | unsigned char(符号なし整数) | 整数 | 1 |
"h" | short(符号付き整数) | 整数 | 2 |
"H" | unsigned short(符号なし整数) | 整数 | 2 |
"i" | int(符号付き整数) | 整数 | 4 |
"I" | unsigned int(符号なし整数) | 整数 | 4 |
"l" | long(符号付き整数) | 整数 | 4 |
"L" | unsigned long(符号なし整数) | 整数 | 4 |
"q" | long long(符号付き整数) | 整数 | 8 |
"Q" | unsigned long long(符号なし整数) | 整数 | 8 |
"f" | float | 浮動小数点 | 4 |
"d" | double | 浮動小数点 | 8 |
"?" | _Bool | bool型 | 1 |
"x" | パディングバイト | ||
"n" | ssize_t | 整数 | |
"N" | size_t | 整数 | |
"e" | 浮動小数点数 | 2 | |
"s" | char[] | bytes | |
"p" | char[] | bytes | |
"p" | void* | 整数 |
使用例
>>> from struct import *
>>> pack("bB",-1,255)
b'\xff\xff'
>>> unpack("bB",b'\xff\xff')
(-1, 255)
またformatの先頭に以下のような文字を追加することで、バイトオーダやサイズ、アライメントなどを設定できる。
文字 | バイトオーダ | サイズ | アライメント |
---|---|---|---|
"@" | native | native | native |
"=" | native | standard | none |
"<" | リトルエンディアン | standard | none |
">" | ビッグエンディアン | standard | none |
"!" | ネットワーク (= ビッグエンディアン) | standard | none |
バイトオーダにおける"native"
ホストマシンに依存したバイトオーダであることを意味する。
サイズおよびアライメントにおける"native"
Cコンパイラのsizeof式で決まることを意味する。
なおこのformatの先頭の文字がいずれかでない場合は、"@"が使われたとみなされる。
使用例
>>> from struct import *
>>> pack(">lll",1,2,3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03'
>>> unpack(">lll",b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> pack("<lll",1,2,3)
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
>>> unpack("<lll",b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00')
(1, 2, 3)
>>> pack("lll",1,2,3)
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
1回目のpackではビッグエンディアンを、2回目のpackではリトルエンディアンを使っている。実行結果から分かる通り、バイト単位で並び順が両者逆転していることがわかる。
3回目のpackでは先頭の文字を省略しているため、"@"が使われているとみなされ、筆者のホストマシンのアーキテクチャ(Intel x64)に合わせてリトルエンディアンが使われている。
終わりに
今回はPyhonでバイナリデータを扱う際に使えるstructライブラリの基本的な使い方を解説した。
structライブラリには今回紹介したpack, unpack以外の関数もいくつか用意されているので、興味がある方はぜひ公式ドキュメントや他の方の記事で各自調べてみてください。
参考文献
- Pythonソフトウェア財団. "struct --- バイト列をパックされたバイナリデータとして解釈する".Python 3.12.1 ドキュメント. 2024-01-14. https://docs.python.org/ja/3/library/struct.html, (参照2024-1-15)