f.seek(500000,0)在到达第500000之前是否会经历文件的所有前499999个字符?
换句话说,是O(n)或O(1)阶的f.seek(n,0)吗?

最佳答案

您需要更加具体地说明对象f是什么类型。
如果f是磁盘上存储的文件的常规 io module对象,则必须确定是否要处理:

  • 原始二进制文件对象
  • 缓冲区对象,包装原始二进制文件
  • 一个TextIO对象,包装了缓冲区
  • 内存中的BytesIOTextIO对象

  • 第一个选项仅使用 lseek system call来重新定位文件描述符的位置。如果此调用为O(1),则取决于操作系统以及所拥有的文件系统类型。对于具有ext4文件系统的Linux系统,请使用 lseek is O(1)
    缓冲区仅清除缓冲区if your seek target is outside of the current buffered region并读入新的缓冲区数据。也是O(1),但是固定成本更高。
    对于文本文件,情况变得更加复杂,因为字节长度可变的编解码器和行尾转换意味着您无法始终将二进制流位置映射到文本位置,而无需从头开始进行扫描。该实现不允许非零的当前位置或相对终点搜索,并且最好是最大程度地减少为绝对搜索读取的数据量。 Internal state shared with the text decoder跟踪recent 'safe point' to seek back to并向前读取到所需位置。最坏的情况是O(n)。
    内存中的文件对象实际上只是很长的可寻址数组。求是O(1),因为您可以更改当前位置指针值。
    还有许多其他文件状对象可能支持也可能不支持搜索。他们如何处理寻求取决于实现。
  • zipfile module支持查找以只读模式打开的zip文件,并且查找到当前缓冲区所覆盖的数据段之前的一个点需要对数据进行完全重新读取和解压缩直到所需的点,然后再查找需要从当前位置开始读取,直到到达新位置为止。 gzip lzma bz2 模块都使用same shared implementation,也使用starts reading from the start if you seek to a point before the current read position(并且没有更大的缓冲区可以避免这种情况)。
  • chunk module允许在块边界内搜索并委托(delegate)给基础对象。如果基础文件查找操作为O(1),则这是O(1)操作。

  • 等等,这要视情况而定。

    关于python - f.seek()在Python中的复杂性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51801213/

    10-09 01:54