在Python中切片文件
我最近在做一个脚本,这个脚本会读取文件,把文件分成小块,然后分析每一块。因为分块的位置是根据内容决定的,所以我需要逐字节读取文件。我不需要随机访问,只是从头到尾线性读取,边读边选择某些位置,然后把从上一个选择的位置到当前的位置的内容给提取出来。
使用内存映射文件配合一个 bytearray
很方便。与其直接返回分块的内容,我返回的是分块的起始位置和大小,让外部的函数来处理切片。
这样做比在 bytearray
中累积当前的分块要快得多(而且比在 bytes
中累积快得多!)。不过我有一些担心的问题想要解决:
bytearray
是不是在复制数据?我以
rb
模式打开文件,并且用mmap
设置为access=mmap.ACCESS_READ
。但是bytearray
本身是一个可变的容器。这会影响性能吗?有没有什么只读的容器可以使用?因为我没有在缓冲区中累积数据,所以我是在随机访问
bytearray
(也就是底层的文件)。即使它可能是缓冲的,我担心根据文件大小和系统内存会出现问题。这真的是个问题吗?
2 个回答
0
你可以试试这个小技巧。
import mmap
class memmap(mmap.mmap):
def read_byte(self):
return ord(super(memmap,self).read_byte())
创建一个新的类,让它继承自mmap类,并且重写默认的read_byte方法。默认的read_byte方法返回的是长度为1的字符串,而你可以把它改成返回一个整数。然后你就可以像使用其他mmap类一样使用这个新类。
希望这对你有帮助。
1
把一个对象转换成可变对象确实会涉及到数据复制。你可以直接通过以下方式把文件读入一个字节数组:
f = open(FILENAME, 'rb') data = bytearray(os.path.getsize(FILENAME)) f.readinto(data)
字符串可以转换成字节数组,所以可能会有性能问题。
字节数组是一个数组,所以它可能会达到 PY_SSIZE_T_MAX/sizeof(PyObject* ) 的限制。想了解更多信息,可以访问 Python数组能有多大?