Pythonバイナリデータ処理
14746 ワード
目次前言 strとbytes base 64モジュール structモジュール 参照リンク 前言
本明細書に係るコードはpython 3に基づいている.x.
strとbytes
コードを書くとき、文字列の処理に関わることがよくありますが、文字列の符号化の問題はよく頭が痛いです.もちろん、この文章は符号化について話すのではなく、主にバイナリ処理について話しています.python 3はbytesを提供してくれました.bytesを利用して符号化エラーの問題をある程度緩和することができます.bytesはバイトシーケンスであり、符号化とは関係ありません.まず例を見てみましょう.
違いが見えますね.文字列を定義するときに、文字列引用符の前に
中国語ではstrが印刷されるのはそれ自体で、bytesが印刷されるのは16進符号化です.ネット上で中国語strを他の人に送信するとき、あなたが使用している符号化フォーマットが相手と一致しない場合、相手がstrを直接読み取るのは文字化けしている可能性がありますが、bytesにはこの問題はありません.上のコードはstrとbytesの変換にも関連していますが、ここでもお話しします.まずコードを見てください.
str回転bytesはencode()メソッド、bytes回転strはdecode()メソッド、encode()メソッドはencoding='utf-8'のデフォルトであることがわかります.またstrには、bytesのほとんどの方法がありますが、この文章は文字列処理の問題を主に話しているわけではないので、ここでは展開しません.
base 64モジュール
次にbase 64モジュールについて説明します.まずbase 64は、64文字でバイナリデータを表す方法である.具体的には、まず、バイナリデータを表す64文字を定義します.
そして、処理が必要なバイナリデータは、3バイト毎のグループ、すなわち
なお、上記の
urlsafeを通ってb 64 encode()符号化文字列は、b 64 encode()符号化文字列とは確かに異なる.また、base 64の64文字の順序はカスタマイズ可能であり、これにより符号化をカスタマイズすることができるが、一般的にはこの必要はない.
structモジュール
最後にstructモジュールについてお話しします.これもpythonでよく使われるバイナリデータを処理するモジュールです.structモジュールはpythonデータとpython bytesオブジェクトとして表されるC構造体(struct)との間の変換を処理するために使用され、アプリケーションシーンは一般的にファイルとネットワーク伝送中のバイナリデータを処理する.structモジュールの応用例を見てみましょう.
上記のようなC構造体があるとしたら、python値とどのように変換しますか?コードを参照:
上記のコードでは、まずpythonで構造体の各メンバーを定義し、pack()メソッドを呼び出してbytesにパッケージ化し、Cとデータ交換を行うことができます.また、次の2行のコードでは、Cからバイナリデータの列を受け取り、unpackメソッドを呼び出して解析することができます(解析されたデータはメタグループに置かれています).次の行のコードでは、C構造体のデータフォーマットを実際に定義します.
1番目のシンボル
Character
Byte Order
Size
Alignment
@
native
native
native
=
native
standard
none
<
little-endian
standard
none
>
big-endian
standard
none
!
network(=big-endian)
standard
none
プログラムを書くときに最初の文字を上記の表の文字として定義しなかった場合、デフォルトは
Format
C Type
Python Type
Standard size
x
pad byte
no value
c
char
bytes of length 1
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
integer
4
I
unsigned int
integer
4
l
long
integer
4
L
unsigned long
integer
4
q
long long
integer
8
Q
unsigned long long
integer
8
n
ssize_t
integer
N
size_t
integer
e
float
2
f
float
float
4
d
double
float
8
s
char[]
bytes
p
char[]
bytes
P
void*
integer
Standard size列に固定値があるのは、プラットフォームに関係なくサイズであり、具体的な値がないのは、プラットフォームに関連していることに注意してください.最後に、上記のコードについては、実際にはこのように書くこともできます.
しかし、この書き方は実例的な方法が優雅ではないと思います.特にコードの中で同じ構造が複数の場所に現れたときです.
リファレンスリンク
廖雪峰base 64教程廖雪峰struct教程python 3 module struct doc
本明細書に係るコードはpython 3に基づいている.x.
strとbytes
コードを書くとき、文字列の処理に関わることがよくありますが、文字列の符号化の問題はよく頭が痛いです.もちろん、この文章は符号化について話すのではなく、主にバイナリ処理について話しています.python 3はbytesを提供してくれました.bytesを利用して符号化エラーの問題をある程度緩和することができます.bytesはバイトシーケンスであり、符号化とは関係ありません.まず例を見てみましょう.
_str = 'str'
print(type(_str))
#
_bytes = b'bytes'
print(type(_bytes))
#
違いが見えますね.文字列を定義するときに、文字列引用符の前に
b
を付けると、bytesが定義されます.上の_bytes変数はバイトシーケンスですが、print()
が出てくるのは文字列の前にb
が付いているだけで、strとあまり変わらないようです.では、次のコードを見てみましょう._str = ' '
print(_str)
#
_bytes = ' '.encode()
print(_bytes)
# b'\xe4\xb8\xad\xe5\x9b\xbd'
中国語ではstrが印刷されるのはそれ自体で、bytesが印刷されるのは16進符号化です.ネット上で中国語strを他の人に送信するとき、あなたが使用している符号化フォーマットが相手と一致しない場合、相手がstrを直接読み取るのは文字化けしている可能性がありますが、bytesにはこの問題はありません.上のコードはstrとbytesの変換にも関連していますが、ここでもお話しします.まずコードを見てください.
_str = ' '
print(type(_str)) #
print(_str) #
_bytes = _str.encode()
print(type(_bytes)) #
print(_bytes) # b'\xe4\xb8\xad\xe5\x9b\xbd'
new_str = _bytes.decode()
print(type(new_str)) #
print(new_str) #
str回転bytesはencode()メソッド、bytes回転strはdecode()メソッド、encode()メソッドはencoding='utf-8'のデフォルトであることがわかります.またstrには、bytesのほとんどの方法がありますが、この文章は文字列処理の問題を主に話しているわけではないので、ここでは展開しません.
base 64モジュール
次にbase 64モジュールについて説明します.まずbase 64は、64文字でバイナリデータを表す方法である.具体的には、まず、バイナリデータを表す64文字を定義します.
['a', 'b', ..., '+', '/'] # 60
そして、処理が必要なバイナリデータは、3バイト毎のグループ、すなわち
3 x 8 = 24 bit
にグループ化される.そしてこの24ビットを4グループに分け,各グループ6ビットとする.各グループの6 bitは0から63の間の数字を表すことができ、最初に定義された64文字テーブルを調べてバイナリデータの文字表現を得ることができます.この場合,元のバイナリデータの長さが増加すると,データ伝送の圧力が増大するのではないか.ここで、base 64が処理する主な処理は、文字化けしの問題を表示することであることを明らかにする必要がある.バイナリファイルを直接開くと、文字化けして出てくることが多いが、base 64で表すと、これらのデータを開くと、メールや画像など、中身がはっきり見える.もちろんURL、Cookie、Webページで少量のデータを転送するためにも使われている.もう一つ質問ですが、元のバイナリデータのバイト数が3の整数倍でなければどうしますか?この場合、base 64は、元のバイナリデータの末尾に\x00
を追加してデータを補完し、その後、符号化された文字列において、これらが補完された箇所を=
と表し、復号化時にこれらの=
が除去され、正確な元のバイナリデータも得られる.これらの操作はpythonのbase 64モジュールで自動的に完了し、実際には関心を持っていません.こんなにたくさん話したので、pythonでbase 64の使い方を見てみましょう.import base64
_bytes = b'test bytes'
b64 = base64.b64encode(_bytes)
print(b64) # b'dGVzdCBieXRlcw=='
new_bytes = base64.b64decode(b64)
print(new_bytes) # b'test bytes'
なお、上記の
b'test bytes'
は10バイトであり、base 64処理後に2つの=
が追加され、12バイト、すなわち3の整数倍となる.最後に、前述したように、base 64はURLを処理するために使用できますが、base 64の64文字には+
/
があり、これらの記号はURLでは直接パラメータとして使用できません.従って、base 64は、base 64が符号化された文字列の+
/
を-
_
に置き換えるurl safeの処理方式も提供する.次に例を示します.import base64
_bytes = b'\xfd\xcf\xbe'
b64 = base64.b64encode(_bytes)
print(b64) # b'/c++'
us_b64 = base64.urlsafe_b64encode(_bytes)
print(us_b64) # b'_c--'
new_bytes = base64.urlsafe_b64decode(us_b64)
print(new_bytes) # b'\xfd\xcf\xbe'
urlsafeを通ってb 64 encode()符号化文字列は、b 64 encode()符号化文字列とは確かに異なる.また、base 64の64文字の順序はカスタマイズ可能であり、これにより符号化をカスタマイズすることができるが、一般的にはこの必要はない.
structモジュール
最後にstructモジュールについてお話しします.これもpythonでよく使われるバイナリデータを処理するモジュールです.structモジュールはpythonデータとpython bytesオブジェクトとして表されるC構造体(struct)との間の変換を処理するために使用され、アプリケーションシーンは一般的にファイルとネットワーク伝送中のバイナリデータを処理する.structモジュールの応用例を見てみましょう.
struct s_data {
unsigned short id;
unsigned int length;
char[5] data;
}
上記のようなC構造体があるとしたら、python値とどのように変換しますか?コードを参照:
from struct import Struct
p_id = 0
p_length = 5
p_data = b'hello'
c_struct = Struct('>HI5s')
packed = c_struct.pack(p_id, p_length, p_data)
print(packed) # b'\x00\x00\x00\x00\x00\x05hello'
unpacked = c_struct.unpack(b'\x00\x00\x00\x00\x00\x05hello')
print(unpacked) # (0, 5, b'hello')
上記のコードでは、まずpythonで構造体の各メンバーを定義し、pack()メソッドを呼び出してbytesにパッケージ化し、Cとデータ交換を行うことができます.また、次の2行のコードでは、Cからバイナリデータの列を受け取り、unpackメソッドを呼び出して解析することができます(解析されたデータはメタグループに置かれています).次の行のコードでは、C構造体のデータフォーマットを実際に定義します.
c_struct = Struct('>HI5s')
1番目のシンボル
>
は、データが大端方式(big-endian)で格納されていることを示し、これは主に、あるC/C++を考慮したコンパイラがバイトアラインメントを使用していることを示す.この文字は、バイト順、サイズ、パッケージング後のデータの位置合わせを定義しています.次の表を参照してください.Character
Byte Order
Size
Alignment
@
native
native
native
=
native
standard
none
<
little-endian
standard
none
>
big-endian
standard
none
!
network(=big-endian)
standard
none
プログラムを書くときに最初の文字を上記の表の文字として定義しなかった場合、デフォルトは
@
です.プラットフォームに関係のないデータフォーマットを処理したい場合は、sizeをstandardとし、nativeを使用しないでください.>
記号の後ろのいくつかの記号のうち、H
はCのunsigned shortを表し、I
はCのunsigned intを表し、s
はCのchar[]を表し、5s
は5要素のchar配列を表す.Cとpythonの対応するタイプを以下に列挙します.Format
C Type
Python Type
Standard size
x
pad byte
no value
c
char
bytes of length 1
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
integer
4
I
unsigned int
integer
4
l
long
integer
4
L
unsigned long
integer
4
q
long long
integer
8
Q
unsigned long long
integer
8
n
ssize_t
integer
N
size_t
integer
e
float
2
f
float
float
4
d
double
float
8
s
char[]
bytes
p
char[]
bytes
P
void*
integer
Standard size列に固定値があるのは、プラットフォームに関係なくサイズであり、具体的な値がないのは、プラットフォームに関連していることに注意してください.最後に、上記のコードについては、実際にはこのように書くこともできます.
import struct
p_id = 0
p_length = 5
p_data = b'hello'
packed = struct.pack('>HI5s', p_id, p_length, p_data)
print(packed) # b'\x00\x00\x00\x00\x00\x05hello'
unpacked = struct.unpack('>HI5s', b'\x00\x00\x00\x00\x00\x05hello')
print(unpacked) # (0, 5, b'hello')
しかし、この書き方は実例的な方法が優雅ではないと思います.特にコードの中で同じ構造が複数の場所に現れたときです.
Struct
インスタンスを作成すると、フォーマット文字列は1回のみ指定され、すべての操作が集中的に処理されます.これにより、コードのメンテナンスが簡単になります(コードを変更するだけでよいため).リファレンスリンク
廖雪峰base 64教程廖雪峰struct教程python 3 module struct doc