2009-03-16 13 views
6

ho qualche codice Python che:Scrivi buffer binario in un file in python

  1. prende un BLOB da un database che viene compressa.
  2. Chiama una routine di compressione in C che decomprime i dati.
  3. Scrive i dati non compressi in un file.

Utilizza ctypes per chiamare la routine C, che si trova in una libreria condivisa.

Questo funziona principalmente, ad eccezione della scrittura effettiva nel file. Per decomprimere, ottengo i dati non compressi in un buffer di pitone, creato utilizzando le ctypes create_string_buffer metodo:

c_uncompData_p = create_string_buffer(64000)

quindi la chiamata di decompressione è come questo:

c_uncompSize = mylib.explodeCharBuffer (c_data_p, c_data_len, c_uncompData_p)

La dimensione del i dati non compressi risultanti vengono restituiti come valore di ritorno.

Ma ... non ho idea di come forzare pitone su un solo scrivere c_uncompSize byte fuori - se faccio:

myfile.write (c_uncompData_p.raw)

scrive l'intero 64k tampone out (i dati sono binari - così non è terminato con null).

Quindi, la mia domanda è: usare Python 2.5 come faccio a stampare i byte c_uncompSize anziché l'intero 64k?

Grazie Jamie

risposta

6

Affettare lavora per c_char_Arrays troppo:

myfile.write(c_uncompData_p[:c_uncompSize]) 
+0

lavori di tranciatura, ma ho il sospetto che crea una copia dei dati. Potrebbe o potrebbe non essere importante (64 K è un numero relativamente piccolo). – jfs

+0

La slicing ha funzionato bene e funziona bene. Grazie! –

+0

Si potrebbe usare 'itertools.islice()' per evitare di fare una copia dei dati, – martineau

5

buffer() potrebbe aiutare ad evitare la copia non necessarie (causata da affettare come in @elo80ka's answer):

myfile.write(buffer(c_uncompData_p.raw, 0, c_uncompSize)) 

Nel tuo esempio non importa (a causa di c_uncompData_p è scritto solo una volta ed è piccolo) ma in generale potrebbe essere utile.


Solo per il gusto di esercizio ecco la risposta che utilizza C stdio s' fwrite():

from ctypes import * 

# load C library 
try: libc = cdll.msvcrt # Windows 
except AttributeError: 
    libc = CDLL("libc.so.6") # Linux 

# fopen() 
libc.fopen.restype = c_void_p 
def errcheck(res, func, args): 
    if not res: raise IOError 
    return res 
libc.fopen.errcheck = errcheck 
# errcheck() could be similarly defined for `fwrite`, `fclose` 

# write data 
file_p = libc.fopen("output.bin", "wb") 
sizeof_item = 1 # bytes 
nitems = libc.fwrite(c_uncompData_p, sizeof_item, c_uncompSize, file_p) 
retcode = libc.fclose(file_p) 
if nitems != c_uncompSize: # not all data were written 
    pass 
if retcode != 0: # the file was NOT successfully closed 
    pass 
+0

Grazie per la risposta. Sia l'affettamento che il metodo del buffer funzionano all'incirca alla stessa velocità per i miei scopi ed entrambi hanno funzionato bene a livello funzionale. –