Pythonに文字列があるとしましょう:
>>> s = 'python'
>>> len(s)
6
今私はencode
このような文字列:
>>> b = s.encode('utf-8')
>>> b16 = s.encode('utf-16')
>>> b32 = s.encode('utf-32')
上記の操作から得られるのはバイト配列です。つまりb
、、は単なるバイト配列です(各バイトはもちろん8ビット長です)。b16
b32
しかし、文字列をエンコードしました。それで、これはどういう意味ですか?「エンコーディング」の概念を生のバイト配列にどのように結び付けるのでしょうか。
答えは、これらのバイト配列のそれぞれが特定の方法で生成されるという事実にあります。これらの配列を見てみましょう。
>>> [hex(x) for x in b]
['0x70', '0x79', '0x74', '0x68', '0x6f', '0x6e']
>>> len(b)
6
この配列は、各文字に対して1バイトがあることを示しています(すべての文字が127を下回るため)。したがって、文字列を「utf-8」に「エンコード」すると、各文字の対応するコードポイントが収集され、配列に配置されます。コードポイントが1バイトに収まらない場合、utf-8は2バイトを消費します。したがって、utf-8は可能な限り最小のバイト数を消費します。
>>> [hex(x) for x in b16]
['0xff', '0xfe', '0x70', '0x0', '0x79', '0x0', '0x74', '0x0', '0x68', '0x0', '0x6f', '0x0', '0x6e', '0x0']
>>> len(b16)
14 # (2 + 6*2)
ここで、「utf-16へのエンコード」は最初に2バイトのBOM(FF FE
)をバイト配列に入れ、その後、各文字について2バイトを配列に入れることがわかります。(この場合、2番目のバイトは常にゼロです)
>>> [hex(x) for x in b32]
['0xff', '0xfe', '0x0', '0x0', '0x70', '0x0', '0x0', '0x0', '0x79', '0x0', '0x0', '0x0', '0x74', '0x0', '0x0', '0x0', '0x68', '0x0', '0x0', '0x0', '0x6f', '0x0', '0x0', '0x0', '0x6e', '0x0', '0x0', '0x0']
>>> len(b32)
28 # (2+ 6*4 + 2)
「utf-32でのエンコード」の場合、最初にBOMを配置し、次に各文字に対して4バイトを配置し、最後に2つのゼロバイトを配列に配置します。
したがって、「エンコーディングプロセス」は、文字列内の文字ごとに1〜2バイトまたは4バイト(エンコーディング名に応じて)を収集し、それらにさらにバイトを追加および追加して、バイトの最終結果配列を作成すると言えます。
さて、私の質問:
- エンコードプロセスについての私の理解は正しいですか、それとも何かが足りませんか?
b
変数のメモリ表現でb16
あり、b32
実際にはバイトのリストであることがわかります。文字列のメモリ表現は何ですか?文字列のメモリには正確に何が格納されていますか?encode()
を実行すると、各文字の対応するコードポイント(エンコーディング名に対応するコードポイント)が収集され、配列またはバイトに入れられることがわかっています。私たちがするとき、正確には何が起こりdecode()
ますか?- utf-16とutf-32では、BOMが付加されていることがわかりますが、utf-32エンコーディングで2つのゼロバイトが付加されているのはなぜですか?