Schreiben Sie Boolesche Zeichenfolge in Binärdatei?

Ich habe eine Reihe von Booleans und ich möchte eine Binärdatei mit diesen Booleans als Bits erstellen. Dies ist, was ich tue:

# 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 

Aber das erzeugt die Ausgabe 1 Byte zu einer Zeit und ist langsam. Was wäre ein effizienter Weg, es zu tun?

6 Solutions collect form web for “Schreiben Sie Boolesche Zeichenfolge in Binärdatei?”

Es sollte schneller sein, wenn du alle deine Bytes zuerst kalkulierst und dann alle zusammen schreibst. Beispielsweise

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

Ich benutze auch ein bytearray das ein natürlicher Container ist, und kann auch direkt in deine Datei geschrieben werden.


Sie können natürlich Bibliotheken verwenden, wenn das passend ist wie Bitarray und Bitstring . Mit dem letzteren konnte man einfach sagen

 bitstring.Bits(bin=boolString).tofile(outputFile) 

Hier ist eine weitere Antwort, diesmal mit einer Industrial-Stärke-Utility-Funktion aus dem PyCrypto – Das Python Cryptography Toolkit, wo in Version 2.6 (die aktuelle letzte stabile Version), ist es in pycrypto-2.6/lib/Crypto/Util/number.py .

Die Kommentare, die vorgehen, sagen:
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 wrt 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 

Sie können einen Booleschen String zu einer long Verwendung mit data = long(boolString,2) . Dann, um diese lange auf die Festplatte zu schreiben, kannst du:

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

Allerdings gibt es keine Notwendigkeit, eine boolesche Zeichenfolge zu machen. Es ist viel einfacher, eine long zu benutzen. Der long Typ kann eine unendliche Anzahl von Bits enthalten. Mit Bitmanipulation können Sie die Bits nach Bedarf einstellen oder löschen. Sie können dann die lange auf Festplatte als Ganzes in einer einzigen Schreiboperation schreiben.

Sie können diesen Code mit der Array- Klasse ausprobieren:

 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() 

Eine Helfer-Klasse (siehe unten) macht es einfach:

 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() 

Verwenden Sie das struct Paket .

Dies kann bei der Bearbeitung von binären Daten, die in Dateien oder aus Netzwerkverbindungen gespeichert sind, unter anderem verwendet werden.

Bearbeiten:

Ein Beispiel mit ? Als das Formatzeichen für ein 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) 

Schauen wir uns die Akte an:

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

Lass es wieder ein:

 with open("out", "rb") as i: q = struct.unpack('????', i.read()) assert q == (True, False, True, False) 
  • Python-Lese aus Datei in mehrere Listen
  • Warum ist dieses numpy Array zu groß, um zu laden?
  • Konvertieren eines Wörterbuchs in das Nummerierungsformat
  • Wie lese ich mehrere Wörterbücher aus einer Datei in Python?
  • Erhalten eines Matlab-Code die Ergebnisse auf Python
  • Wie füge ich eine neue Zeile vor der ersten Zeile in eine Datei mit python ein?
  • Wx.TextCtrl.LoadFile ()
  • So vermeiden Sie Speicherleck mit shared_ptr und SWIG
  • "Listenindex außerhalb des zulässigen Bereichs", wenn man versucht, Zeilen aus einer Textdatei mit python auszutragen
  • Python nicht erkennen Verzeichnisse os.path.isdir ()
  • Technik zur Verwendung von std :: ifstream, std :: ofstream in python über SWIG?
  • Python ist die beste Programmiersprache der Welt.