2

ブール値の文字列があり、これらのブール値をビットとして使用してバイナリ ファイルを作成したいと考えています。これは私がやっていることです:

# first append the string with 0s to make its length a multiple of 8
while len(boolString) % 8 != 0:
    boolString += '0'

# write the string to the file byte by byte
i = 0
while i < len(boolString) / 8:
    byte = int(boolString[i*8 : (i+1)*8], 2)
    outputFile.write('%c' % byte)

    i += 1

ただし、これは一度に 1 バイトの出力を生成し、低速です。それを行うためのより効率的な方法は何ですか?

4

6 に答える 6

2

最初にすべてのバイトを計算してから、それらをまとめて書き込むと、より速くなるはずです。例えば

b = bytearray([int(boolString[x:x+8], 2) for x in range(0, len(boolString), 8)])
outputFile.write(b)

また、使用する自然なコンテナーである aも使用してbytearrayおり、ファイルに直接書き込むこともできます。


もちろん、必要に応じてbitarraybitstringなどのライブラリを使用できます。後者を使用すると、あなたはただ言うことができます

bitstring.Bits(bin=boolString).tofile(outputFile)
于 2012-10-01T11:32:30.637 に答える
2

今回は、バージョン 2.6 (現在の最新の安定版リリース) で定義されているPyCrypto - The Python Cryptography Toolkitの強力なユーティリティ関数を使用しpycrypto-2.6/lib/Crypto/Util/number.pyます。

それに先行するコメントは次のように述べています。
    Improved conversion functions contributed by Barry Warsaw, after careful benchmarking

import struct

def long_to_bytes(n, blocksize=0):
    """long_to_bytes(n:long, blocksize:int) : string
    Convert a long integer to a byte string.

    If optional blocksize is given and greater than zero, pad the front of the
    byte string with binary zeros so that the length is a multiple of
    blocksize.
    """
    # after much testing, this algorithm was deemed to be the fastest
    s = b('')
    n = long(n)
    pack = struct.pack
    while n > 0:
        s = pack('>I', n & 0xffffffffL) + s
        n = n >> 32
    # strip off leading zeros
    for i in range(len(s)):
        if s[i] != b('\000')[0]:
            break
    else:
        # only happens when n == 0
        s = b('\000')
        i = 0
    s = s[i:]
    # add back some pad bytes.  this could be done more efficiently w.r.t. the
    # de-padding being done above, but sigh...
    if blocksize > 0 and len(s) % blocksize:
        s = (blocksize - len(s) % blocksize) * b('\000') + s
    return s
于 2012-10-01T22:34:06.873 に答える
1

ヘルパークラス(以下に表示)を使用すると、次のことが簡単になります。

class BitWriter:
    def __init__(self, f):
        self.acc = 0
        self.bcount = 0
        self.out = f

    def __del__(self):
        self.flush()

    def writebit(self, bit):
        if self.bcount == 8 :
            self.flush()
        if bit > 0:
            self.acc |= (1 << (7-self.bcount))
        self.bcount += 1

    def writebits(self, bits, n):
        while n > 0:
            self.writebit( bits & (1 << (n-1)) )
            n -= 1

    def flush(self):
        self.out.write(chr(self.acc))
        self.acc = 0
        self.bcount = 0

with open('outputFile', 'wb') as f:
    bw = BitWriter(f)
    bw.writebits(int(boolString,2), len(boolString))
    bw.flush()
于 2012-10-01T13:25:03.410 に答える
1

配列クラスを使用してこのコードを試すことができます。

import array

buffer = array.array('B')

i = 0
while i < len(boolString) / 8:
    byte = int(boolString[i*8 : (i+1)*8], 2)
    buffer.append(byte)
    i += 1

f = file(filename, 'wb')
buffer.tofile(f)
f.close()
于 2012-10-01T11:31:12.510 に答える
1

longブール文字列をusingに変換できますdata = long(boolString,2)。次に、これをディスクに書き込むには、次を使用できます。

while data > 0:
    data, byte = divmod(data, 0xff)
    file.write('%c' % byte)

ただし、ブール文字列を作成する必要はありません。を使用する方がはるかに簡単longです。long型には無限のビット数を含めることができます。ビット操作を使用して、必要に応じてビットを設定またはクリアできます。その後、1 回の書き込み操作で long をディスク全体に書き込むことができます。

于 2012-10-01T11:32:04.633 に答える
0

structパッケージを使用します。

これは、ファイルに格納されたバイナリ データやネットワーク接続などのソースを処理する際に使用できます。

編集:

のフォーマット文字?として使用する例。bool

import struct

p = struct.pack('????', True, False, True, False)
assert p == '\x01\x00\x01\x00'
with open("out", "wb") as o:
    o.write(p)

ファイルを見てみましょう。

$ ls -l out
-rw-r--r-- 1 lutz lutz 4 Okt  1 13:26 out
$ od out
0000000 000001 000001
000000

もう一度読んでください:

with open("out", "rb") as i:
    q = struct.unpack('????', i.read())
assert q == (True, False, True, False)
于 2012-10-01T11:15:41.147 に答える