2013-08-21 21 views
61

Ho una lista di byte come numeri interi, che è qualcosa comePython come scrivere in un file binario?

[120, 3, 255, 0, 100] 

Come posso scrivere questo elenco in un file in formato binario?

Questo lavoro dovrebbe funzionare?

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

Si chiede "Funzionerebbe?". L'hai provato? – StephenTG

+0

Dovrebbe essere 'TypeError: l'argomento 1 deve essere string o buffer, non list'. –

risposta

62

Questo è esattamente ciò che è per bytearray:

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

Se stai usando Python 3.x, è possibile utilizzare bytes invece (e probabilmente dovrebbe, come segnala la vostra intenzione meglio). Ma in Python 2.x, questo non funzionerà, perché bytes è solo un alias per str. Come al solito, mostrare con l'interprete interattivo è più facile che spiegare con il testo, quindi fammelo fare.

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

Uso piacevole dei tipi predefiniti. Basta notare che bytearray è stato aggiunto in 2.6, se si desidera supportare i sistemi legacy, dovrebbe essere evitato. – Perkins

+5

@Perkins: Certo, e dovresti evitare le espressioni del generatore se devi lavorare su 2.3, fai attenzione con 'str.encode' e' struct.pack' se devi lavorare su 2.2. Ma 2.6 è uscito da 5 anni; tutti e tre gli Ubuntu LTS sono ancora in supporto, tutte e tre le versioni di OS X in supporto, la precedente versione principale di CentOS/RHEL, ecc., tutto viene integrato. Se hai bisogno di supportare 2.5 o 2.1 o 1.6 o qualsiasi altra cosa, probabilmente Conoscere ... – abarnert

+3

Con Python 2 su Windows, ho trovato che scrivere un 'bytearray' converte ancora' \ n' in '\ r \ n', rendendolo insoddisfacente per i dati binari, se il flag" b "non viene passato quando si apre il file. – feersum

18

Usa struct.pack per convertire i valori interi in byte binari, quindi scrivere i byte. Per esempio.

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

Tuttavia vorrei mai dare un file binario un'estensione .txt.

Il vantaggio di questo metodo è che funziona anche per altri tipi, ad esempio se uno qualsiasi dei valori era maggiore di 255, è possibile utilizzare '5i' per il formato per ottenere interi interi a 32 bit.

+0

.txt va bene se hai modo di sapere che i dati che stai scrivendo rientrano tutti nell'intervallo di ascii stampabile. Tuttavia, in questo caso sei corretto, poiché i dati di esempio includono caratteri non stampabili. – Perkins

+0

@Perkins Non ho assunto il presupposto che i valori sarebbero addirittura inferiori a 256 molto meno nell'intervallo ASCII. Anche se lo fossero, i file .txt dovrebbero essere riservati a quelli che hanno senso per un essere umano che non si applica mai ai dati binari. –

+1

Hai ragione, struct.pack è anche la strada da percorrere se stai scrivendo dati con valori superiori a 255, dato che né bytearray né chr possono gestire valori interi più grandi. – Perkins

7

convertire da interi < 256 a binario, utilizzare la funzione chr. Quindi stai cercando di fare quanto segue.

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

È possibile utilizzare il seguente esempio di codice utilizzando Python 3 sintassi:

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

Ecco conchiglia one-liner:

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

Come di Python 3.2+, è anche possibile compiere utilizzando il metodo nativo to_bytes:

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

I.e., ogni singola chiamata a to_bytes crea in questo caso una stringa di lunghezza 1, con i suoi caratteri disposti in ordine big-endian (che è banale per stringhe di lunghezza 1), che rappresenta il valore intero byte.È inoltre possibile ridurre le ultime due righe in una sola:

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

Usa sottaceto, in questo modo: import salamoia

Il codice sarà simile a questa:

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

Per leggere i dati indietro, utilizzare il metodo pickle.load

Problemi correlati