2013-08-21 19 views
61

Ich habe eine Liste von Bytes als ganze Zahlen, die wie etwasPython wie in eine Binärdatei schreiben?

ist
[120, 3, 255, 0, 100] 

Wie kann ich diese Liste in eine Datei als binäre schreiben?

Würde das funktionieren?

newFileBytes = [123, 3, 255, 0, 100] 
# make file 
newFile = open("filename.txt", "wb") 
# write to file 
newFile.write(newFileBytes) 
+31

Du fragst "Würde das funktionieren?". Hast du es versucht? – StephenTG

+0

Sollte 'TypeError: Argument 1 muss Zeichenfolge oder Puffer, nicht Liste sein. –

Antwort

62

Dies ist genau das, was bytearray ist für:

newFileByteArray = bytearray(newFileBytes) 
newFile.write(newFileByteArray) 

Wenn Sie Python 3.x verwenden, können Sie bytes stattdessen verwenden (und sollte wahrscheinlich, wie es signalisiert Ihre Absicht besser). Aber in Python 2.x wird das nicht funktionieren, weil bytes nur ein Alias ​​für str ist. Wie üblich ist das Zeigen mit dem interaktiven Dolmetscher einfacher als das Erklären mit Text, also lass mich das einfach machen.

Python 3.x:

>>> bytearray(newFileBytes) 
bytearray(b'{\x03\xff\x00d') 
>>> bytes(newFileBytes) 
b'{\x03\xff\x00d' 

Python 2.x:

>>> bytearray(newFileBytes) 
bytearray(b'{\x03\xff\x00d') 
>>> bytes(newFileBytes) 
'[123, 3, 255, 0, 100]' 
+0

Schöne Verwendung von eingebauten Typen. Beachten Sie, dass das Bytearray in 2.6 hinzugefügt wurde, wenn Sie Legacy-Systeme unterstützen möchten, sollte es vermieden werden. – Perkins

+5

@Perkins: Sicher, und Sie sollten Generatorausdrücke vermeiden, wenn Sie an 2.3 arbeiten müssen, seien Sie vorsichtig mit beiden "str.encode" und "struct.pack", wenn Sie an 2.2 arbeiten müssen. Aber 2,6 ist jetzt seit 5 Jahren draußen; Alle drei Ubuntu LTSs sind noch in der Unterstützung, alle drei OS X Versionen, die vorherige Hauptversion von CentOS/RHEL, etc., alle sind mit eingebaut. Wenn Sie 2.5 oder 2.1 oder 1.6 oder was auch immer unterstützen müssen wissen ... – abarnert

+3

Mit Python 2 unter Windows habe ich festgestellt, dass das Schreiben eines 'bytearray' trotzdem '\ n' in' \ r \ n' konvertiert, was es für binäre Daten nicht befriedigend macht, wenn das "b" Flag nicht beim Öffnen des Datei. – feersum

18

struct.pack Verwenden der ganzzahligen Werte in binäre Bytes umzuwandeln, dann die Bytes schreiben. Z.B.

newFile.write(struct.pack('5B', *newFileBytes)) 

Allerdings würde ich nie eine binäre Datei, die eine .txt Erweiterung geben.

Der Vorteil dieser Methode ist, dass es auch für andere Typen funktioniert, zum Beispiel, wenn einer der Werte größer als 255 ist, können Sie stattdessen '5i' für das Format verwenden, um volle 32-Bit-Ganzzahlen zu erhalten.

+0

.txt ist in Ordnung, wenn Sie wissen müssen, dass die Daten, die Sie schreiben, in den druckbaren ASCII-Bereich fallen. Allerdings sind Sie in diesem Fall richtig, da die Beispieldaten nicht druckbare Zeichen enthalten. – Perkins

+0

@Perkins Ich habe nicht die Annahme gemacht, dass die Werte im ASCII-Bereich sogar weniger als 256 viel weniger wären. Selbst wenn dies der Fall ist, sollten .txt-Dateien für diejenigen reserviert werden, die für einen Menschen Sinn ergeben, der niemals für Binärdaten gilt. –

+1

Sie haben Recht, struct.pack ist auch der Weg zu gehen, wenn Sie Daten mit Werten über 255 schreiben werden, da weder bytearray noch chr größere Integer-Werte verarbeiten können. – Perkins

7

Um aus ganzen Zahlen < 256 in binäre zu konvertieren, verwenden Sie die chr Funktion. Sie sehen also folgendes an.

newFileBytes=[123,3,255,0,100] 
newfile=open(path,'wb') 
newfile.write((''.join(chr(i) for i in newFileBytes)).encode('ascii')) 
3

Sie können den folgenden Code ein Beispiel unter Verwendung von Python 3 Syntax:

from struct import pack 
with open("foo.bin", "wb") as file: 
    file.write(pack("<IIIII", *bytearray([120, 3, 255, 0, 100]))) 

Hier Schale Einzeiler ist:

python -c $'from struct import pack\nwith open("foo.bin", "wb") as file: file.write(pack("<IIIII", *bytearray([120, 3, 255, 0, 100])))' 
1

Ab Python 3.2 +, können Sie auch erreichen können dies mit der to_bytes native int-Methode:

newFileBytes = [123, 3, 255, 0, 100] 
# make file 
newFile = open("filename.txt", "wb") 
# write to file 
for byte in newFileBytes: 
    newFile.write(byte.to_bytes(1, byteorder='big')) 

D. h., Jeder einzelne Aufruf an to_bytes erzeugt in diesem Fall eine Zeichenfolge der Länge 1, deren Zeichen in Big-Endian-Reihenfolge angeordnet sind (was für Längen-1-Zeichenfolgen trivial ist), was den Ganzzahlwert byte darstellt.

newFile.write(''.join([byte.to_bytes(1, byteorder='big') for byte in newFileBytes])) 
0

Verwenden Gurke, wie folgt aus:: import Beize

Ihr Code würde wie folgt aussehen:

import pickle 
mybytes = [120, 3, 255, 0, 100] 
with open("bytesfile", "wb") as mypicklefile: 
    pickle.dump(mybytes, mypicklefile) 

Zum Lesen der Daten Sie können auch die letzten beiden Zeilen zu einem einzigen verkürzen zurück, benutze die pickle.load-Methode

Verwandte Themen