在Python中切片文件

14 投票
2 回答
2465 浏览
提问于 2025-05-01 00:43

我最近在做一个脚本,这个脚本会读取文件,把文件分成小块,然后分析每一块。因为分块的位置是根据内容决定的,所以我需要逐字节读取文件。我不需要随机访问,只是从头到尾线性读取,边读边选择某些位置,然后把从上一个选择的位置到当前的位置的内容给提取出来。

使用内存映射文件配合一个 bytearray 很方便。与其直接返回分块的内容,我返回的是分块的起始位置和大小,让外部的函数来处理切片。

这样做比在 bytearray 中累积当前的分块要快得多(而且比在 bytes 中累积快得多!)。不过我有一些担心的问题想要解决:

  1. bytearray 是不是在复制数据?

  2. 我以 rb 模式打开文件,并且用 mmap 设置为 access=mmap.ACCESS_READ。但是 bytearray 本身是一个可变的容器。这会影响性能吗?有没有什么只读的容器可以使用?

  3. 因为我没有在缓冲区中累积数据,所以我是在随机访问 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
  1. 把一个对象转换成可变对象确实会涉及到数据复制。你可以直接通过以下方式把文件读入一个字节数组:

    f = open(FILENAME, 'rb')
    data = bytearray(os.path.getsize(FILENAME))
    f.readinto(data)
    

来自 http://eli.thegreenplace.net/2011/11/28/less-copies-in-python-with-the-buffer-protocol-and-memoryviews#id12

  1. 字符串可以转换成字节数组,所以可能会有性能问题。

  2. 字节数组是一个数组,所以它可能会达到 PY_SSIZE_T_MAX/sizeof(PyObject* ) 的限制。想了解更多信息,可以访问 Python数组能有多大?

撰写回答