在Python中将二进制缓冲区写入文件

6
我有一些Python代码,它可以:
  1. 从数据库中获取一个被压缩的BLOB。
  2. 调用C中的解压缩例程来解压缩数据。
  3. 将未压缩的数据写入文件。
它使用ctypes调用位于共享库中的C程序。这基本上是有效的,除了实际写入文件之外。为了进行解压缩,我将数据解压缩到一个Python缓冲区中,该缓冲区是使用ctypes的create_string_buffer方法创建的: c_uncompData_p = create_string_buffer(64000) 因此,解压缩调用如下: c_uncompSize = mylib.explodeCharBuffer (c_data_p, c_data_len, c_uncompData_p) 返回未压缩数据的大小作为返回值。但是……我不知道如何强制Python仅写入c_uncompSize字节——如果我这样做: myfile.write (c_uncompData_p.raw) 它将整个64k缓冲区输出(数据是二进制的,因此没有空终止符)。那么,我的问题是 - 如何使用Python 2.5打印c_uncompSize字节,而不是整个64k?谢谢 Jamie。
2个回答

6

切片也适用于c_char_Arrays:

myfile.write(c_uncompData_p[:c_uncompSize])

切片功能可以使用,但我怀疑它会创建数据的副本。这可能重要,也可能不重要(64K是相对较小的数字)。 - jfs
可以使用 itertools.islice() 来避免复制数据。 - martineau

6

buffer() 可以帮助避免不必要的复制(例如像 @elo80ka 的答案 中所示的切片):

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

在你的例子中,这并不重要(由于 c_uncompData_p 只写了一次且很小),但通常情况下它可能会有用。
仅出于练习的目的,以下是使用C stdio 的 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

感谢您的回答。对于我的目的,切片和缓冲区方法的运行速度大致相同,并且在功能上都很好。 - Jamie Love

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接