コードを作成する前に、私は1つの推奨をしたいと思います。「ビットフィールド」の値は、バイトに分割できる長さではありません。私はあなたがビット列を扱っているときはいつでも、あなたはそれらをバイトの大きさで成長させることを提案したいと思います(例えばlen(ビットフィールド)%8!= 0:print 'ビットフィールドが完全にバイトで表現できることを確認してください)異なるプログラミング言語、プログラミング言語内の異なるライブラリ、および異なるデータベースでフィールドがどのように操作されるかにあいまいさがないことを確認してください。言い換えれば、データベース、Python、私が推薦しようとしているライブラリなどはすべて、このビット配列を格納するか、バイト配列の形で表現できるかのどちらかです。提供されたビット配列が均等にバイトに分割されない場合、次の3つのうちの1つが発生します。 1)エラーが発生します(これは楽観的です)。 2)ビット配列は自動的にパディングされます。 3)ビット配列は自動的に魔法のように右に詰め込まれます。
ある種のビットストリングライブラリの使用をお勧めします。私はこの目的のためにpython-bitstringを使用しました。私はここでODBCに対処するための時間はかかりませんでしたが、考え方は基本的に同じであり、srgergの答えを活用:
例:
#!/usr/bin/python
import pymssql
from binascii import hexlify
from bitstring import BitArray
dbconninfo = {'host': 'hostname', 'user': 'username', 'password': 'secret', 'database': 'bitexample', 'as_dict': True}
conn = pymssql.connect(**dbconninfo)
cursor = conn.cursor()
bitfield = "000001110100111000110101100010"
ba = BitArray(bin=bitfield)
print '%32d (bitfield -> BitArray -> int)' % ba.int
cursor.execute("CREATE TABLE bin_test (bin_col varbinary(max))")
cursor.execute("INSERT INTO bin_test values (%s)", (ba.int,))
cursor.execute("SELECT bin_col FROM bin_test")
results = cursor.fetchone()['bin_col'] # results now contains binary packed data '\x01\xd3\x8db'
conn.rollback()
results_int = int(hexlify(results),16)
print '%32d (bitfield -> BitArray -> int -> DB (where data is binary packed) -> unpacked with hexlify -> int)' % results_int
print '%32s (Original bitfield)' % bitfield
from_db_using_ba_hexlify_and_int_with_length = BitArray(int=int(hexlify(results),16), length=30).bin
print '%32s (From DB, decoded with hexlify, using int to instantiate BitArray, specifying length of int as 30 bits, out as bin)' %
from_db_using_ba_hexlify_and_int_with_length
from_db_using_ba_hex = BitArray(hex=hexlify(results)).bin # Can't specify length with hex
print '%32s (From DB, decoded with hexlify, using hex to instantiate BitArray, can not specify length, out as bin)' % from_db_using_ba_hex
from_db_using_ba_bytes_no_length = BitArray(bytes=results).bin # Can specify length with bytes... that's next.
print '%32s (From DB, using bytes to instantiate BitArray, no length specified, out as bin)' % from_db_using_ba_bytes_no_length
from_db_using_ba_bytes = BitArray(bytes=results,length=30).bin
print '%32s (From DB, using bytes to instantiate BitArray, specifying length of bytes as 30 bits, out as bin)' % from_db_using_ba_bytes
from_db_using_hexlify_bin = bin(int(hexlify(results),16))
print '%32s (from DB, decoded with hexlify -> int -> bin)' % from_db_using_hexlify_bin
from_db_using_hexlify_bin_ba = BitArray(bin=bin(int(hexlify(results),16))).bin
print '%32s (from DB, decoded with hexlify -> int -> bin -> BitArray instantiated with bin)' % from_db_using_hexlify_bin
from_db_using_bin = bin(int(results,16))
print '%32s (from DB, no decoding done, using bin)' % from_db_using_bin
これの出力は次のとおりです。
30641506 (bitfield -> BitArray -> int)
30641506 (bitfield -> BitArray -> int -> DB (where data is binary packed) -> unpacked with hexlify -> int)
000001110100111000110101100010 (Original bitfield)
000001110100111000110101100010 (From DB, decoded with hexlify, using int to instantiate BitArray, specifying length of int as 30 bits, out as bin)
00000001110100111000110101100010 (From DB, decoded with hexlify, using hex to instantiate BitArray, can not specify length, out as bin)
00000001110100111000110101100010 (From DB, using bytes to instantiate BitArray, no length specified, out as bin)
000000011101001110001101011000 (From DB, using bytes to instantiate BitArray, specifying length of bytes as 30 bits, out as bin)
0b1110100111000110101100010 (from DB, decoded with hexlify -> int -> bin)
0b1110100111000110101100010 (from DB, decoded with hexlify -> int -> bin -> BitArray instantiated with bin)
Traceback (most recent call last):
File "./bitexample.py", line 38, in <module>
from_db_using_bin = bin(int(results,16))
ValueError: invalid literal for int() with base 16: '\x01\xd3\x8db'
ビットストリングをバイトに直接分解することはできません(30ビットを表すストリング)正確なを取得する唯一の方法は、長さを指定することでした。結果は一貫していなかったBitArrayがどのようにインスタンス化されたかで終わります。
先頭の0を保持する方法はありますか?それはビットフィールドなので重要です。 – Slruh
あなたが知っているビット数がある場合は、あらかじめPython文字列フォーマットを使用して文字列をゼロで埋め込むことができます。たとえば、30ビットが必要な場合は、上のサンプルコードの最後の行を '" {:030b} "に置き換えることができます(format.unpack("> I "、result [0])[0] ) '' 000001110100111000110101100010 ''になります。 – srgerg