2009-03-16 3 views
6

У меня есть некоторый код, который питон:Дать двоичный буфер в файл в Python

  1. принимает BLOB из базы данных, которая сжимается.
  2. Вызывает процедуру сжатия в C, которая распаковывает данные.
  3. Записывает несжатые данные в файл.

Он использует ctypes для вызова подпрограммы C, которая находится в общей библиотеке.

Это в основном работает, за исключением фактического написания файла. Для того, чтобы распаковывать, я получаю несжатые данные в буфер питона, созданные с использованием ctypes create_string_buffer метода:

c_uncompData_p = create_string_buffer(64000)

поэтому вызов распаковки выглядит так:

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

Размер полученные несжатые данные возвращаются как возвращаемое значение.

... Но я понятия не имею, как заставить питона на писать только c_uncompSize байт из - если я:

myfile.write (c_uncompData_p.raw)

записывает весь 64k буфер из (данные двоичного кода - так он не завершается нулем).

Итак, мой вопрос заключается в использовании Python 2.5, как мне получить распечатку байтов c_uncompSize, а не всего 64k?

Благодаря Джейми

ответ

6

нарезка работает c_char_Arrays тоже:

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

нарезая работает, но я подозреваю, что он создает копию данных. Это может быть или не быть важно (64K - относительно небольшое число). – jfs

+0

Нарезка работала хорошо и хорошо работает. Благодаря! –

+0

Можно использовать 'itertools.islice()', чтобы избежать копирования данных, – martineau

5

buffer() может помочь избежать ненужного копирования (вызванного нарезка, как в @elo80ka's answer):

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

В вашем примере это не имеет значения (из-за c_uncompData_p написано только один раз и мало), но в целом он мог быть полезным.


Просто ради упражнений вот ответ, который использует 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

Спасибо за ваш ответ. Как срез, так и метод буфера работают с одинаковой скоростью для моих целей, и оба функционально работают нормально. –

Смежные вопросы