ホームページ  >  記事  >  バックエンド開発  >  Pythonのstructを使ってバイナリデータを処理する方法を詳しく解説

Pythonのstructを使ってバイナリデータを処理する方法を詳しく解説

巴扎黑
巴扎黑オリジナル
2017-09-13 10:05:341993ブラウズ

この記事では主に、struct を使用してバイナリを処理する Python の詳細な例に関する関連情報を紹介します。この部分の内容を必要な方はこの記事を通じてマスターしていただければ幸いです。

Python の詳細な例。 struct を使用してバイナリを処理する

はい ファイルへのアクセスやソケット操作など、Python を使用してバイナリ データを処理する必要がある場合、Python の struct モジュールを使用して構造体の処理を完了できます。 C言語の

  • structモジュール 3つの最も重要な関数はpack()、unpack()、calcsize()です

  • pack(fmt, v1, v2, ...) データをパックします。指定された形式 (fmt) に従った文字列 (実際には、C 構造体に似たバイト ストリームです)

  • unpack(fmt, string) 指定された形式 (fmt) に従ってバイト ストリーム文字列を解析し、解析されたタプルを返します

  • calcsize(fmt ) 指定された形式 (fmt) が占めるメモリのバイト数を計算します

構造体でサポートされている形式は次のとおりです:

fdspchar[]string1Pvoid *長い注 1.q と Q は、マシンが 64 ビット動作をサポートしている場合にのみ興味深いです注 3. s 形式は、a の文字列を表します特定の長さ、4s は長さ 4 の文字列を表しますが、p はパスカル文字列を表します注 5。最後のものは次の目的で使用できます。 4 バイトを占めるポインター型を表します。 @native
Format C Type Python バイト数
x パッドバイト 値なし 1
c char 長さ1の文字列 1
b 署名付き文字 integer 1
B unsigned char integer 1
? _Bool bool 1
h short int eger 2
H unsigned short integer 2
i int integer 4
I unsigned int 整数または長整数 4
l long integer 4
H ed long long long 8
float float 4
double float 8
char[] string 1
注 2. 各形式は、数値を表す数字がある前に使用できます注 4.P はポインタを変換するために使用され、その長さはマシン語の長さに関連します C の構造体とデータを交換するには、一部の C または C++ コンパイラーがワードを使用することも考慮する必要があります セクションのアライメントは、通常 32 ビット システムでは 4 バイトであるため、構造体はローカル マシンのバイト オーダーに従って変換されます。フォーマットの最初の文字を使用してアライメントを変更できます。定義は次のとおりです。
サイズとアライメント

native 4バイトを構成



=

native


standard 元のバイト数に従って

による標準元のバイト数 & gt; ビッグエンディアン元のバイト数に基づく! ネットワーク (= ビッグエンディアン)

使用方法は、'@5s6sif'のようにfmtの先頭に置くだけです

例1:

例えば、ソケット経由で受け取った


struct Header
{
  unsigned short id;
  char[4] tag;
  unsigned int version;
  unsigned int count;
}

という構造体があります。 .recv 構造データは文字列 s に存在します。ここで、unpack() 関数を使用する必要があります。上記の形式文字列では、! はネットワーク バイトを使用することを意味します。データはネットワークから受信されるため、次の H は符号なしの短い ID を表し、4s は 4 バイトの長さの文字列を表し、2I は 2 つの Unsigned int 型を表します。データ。

アンパックにより、情報が ID、タグ、バージョン、カウントに保存されました


同様に、ローカル データを構造体形式にパックすることも非常に便利です


import struct id, tag, version, count = struct.unpack("!H4s2I", s)

。関数は、指定された形式に従って ID、タグ、バージョン、カウントを構造体に変換します。 ss は文字列 (実際には C 構造体に似たバイト ストリーム) になり、この文字列はソケット.send(ss) を通じて送信できます。

例 2:

ss = struct.pack("!H4s2I", id, tag, version, count);
このとき、bytes は文字列 string であり、byte ごとの文字列は のバイナリ記憶内容と同じです。

次に、逆の操作を実行します


既存のバイナリ データ バイト (実際には文字列) を Python データ型に変換します:


import struct
a=12.34
#将a变为二进制
bytes=struct.pack('i',a)

unpack はタプルを返すことに注意してください

変数は 1 つだけです:


a,=struct.unpack('i',bytes)

次に、


bytes=struct.pack('i',a)

をデコードするときは次のようにする必要があります。 a=struct.unpack('i', bytes) を直接使用する場合、a=( 12.34, ) は、元の浮動小数点数ではなくタプルです。

複数のデータで構成されている場合は、次のようになります。


a,=struct.unpack('i',bytes) 或者 (a,)=struct.unpack('i',bytes)

このときのバイトはバイナリ形式のデータであり、binfile.write(bytes) のようにファイルに直接書き込むことができます。

その後、必要に応じて読み出すことができたら、 bytes=binfile.read()

そして、struct.unpack()を通してPython変数にデコードします


a='hello'
b='world!'
c=2
d=45.123
bytes=struct.pack('5s6sif',a,b,c,d)

'5s6sif'が呼び出されますfmt は、数字と文字で構成されます。5s は 5 文字の文字列を表し、2i は 2 つの整数を表します。ctype は、次のような種類に対応することを意味します。パイソン。

注: バイナリ ファイルの処理中に問題が発生しました

バイナリ ファイルを処理するときは、次のメソッドを使用する必要があります


a,b,c,d=struct.unpack('5s6sif',bytes)

それでは、binfile=open(filepath,'r') の結果はどうなりますか?違いは何ですか?

2 つの違いがあります:


まず、「r」を使用するときに「0x1A」に遭遇すると、それはファイルの終わり、つまり EOF とみなされます。 「rb」を使用すると、この問題は発生しません。つまり、バイナリで書き込み、テキストで読み出す場合、「0X1A」が存在するとファイルの一部だけが読み出されます。 「rb」を使用すると、ファイルの最後まで読み取られます。

2 番目に、文字列 x='abcndef' の場合、len(x) を使用して長さを 7 にします。n を改行文字と呼び、実際には '0X0A' です。テキストモードである「w」で記述すると、「0X0A」は Windows プラットフォーム上で自動的に「0X0D」、「0X0A」の 2 文字に変更されます。つまり、実際のファイル長は 8 になります。 「r」テキスト モードで読み取ると、元の改行文字に自動的に変換されます。書き込み時に「wb」バイナリモードに変更すると、1文字は変更されず、読み取り時にそのまま読み込まれます。したがって、テキスト モードで書き込み、バイナリ モードで読み取る場合は、この余分なバイトを考慮する必要があります。 「0X0D」は復帰文字とも呼ばれます。 Linuxでは変わりません。 Linux は改行を表すために「0X0A」のみを使用するためです。

元のバイト数に基づく

以上がPythonのstructを使ってバイナリデータを処理する方法を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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