2009-03-16 43 views
6

Tengo algo de código Python que:Escribir un búfer binario en un archivo en Python

  1. Toma un BLOB de una base de datos que se comprime.
  2. Llama a una rutina de descompresión en C que descomprime los datos.
  3. Escribe los datos sin comprimir en un archivo.

Utiliza ctypes para llamar a la rutina C, que se encuentra en una biblioteca compartida.

Esto funciona principalmente, a excepción de la escritura real en el archivo. Para descomprimir, consigo los datos sin comprimir en un búfer pitón, creada usando los ctypes create_string_buffer método:

c_uncompData_p = create_string_buffer(64000)

lo que la llamada descompresión es así:

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

El tamaño de la los datos sin comprimir resultantes se devuelven como el valor de retorno.

Pero ... no tienen idea de cómo forzar pitón en escribir solamente c_uncompSize bytes - si lo hago:

myfile.write (c_uncompData_p.raw)

se escribe todo el búfer fuera de 64k (los datos son binarios - por lo no es nulo terminado).

Por lo tanto, mi pregunta es - usando Python 2.5 ¿cómo obtengo los bytes de c_uncompSize impresos, en lugar de los 64k completos?

Gracias Jamie

Respuesta

6

rebanar trabaja para c_char_Arrays también:

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

trabajos de cortado, pero sospecho que crea una copia de los datos. Puede o no ser importante (64K es un número relativamente pequeño). – jfs

+0

El corte funcionaba bien y funciona bien. ¡Gracias! –

+0

Se podría usar 'itertools.islice()' para evitar hacer una copia de los datos, – martineau

5

buffer() podría ayudar a evitar copias innecesarias (causada por corte como en @elo80ka's answer):

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

En su ejemplo no importa (debido a c_uncompData_p está escrito solo una vez y es pequeño) pero en general podría sé útil.


Sólo por el bien de ejercicio aquí es la respuesta que utiliza 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

Gracias por su respuesta. Tanto el método de división como el método de búfer se ejecutan aproximadamente a la misma velocidad para mis propósitos y ambos funcionaron correctamente. –

Cuestiones relacionadas