f.seek(500000,0)在到达500000之前是否经历了文件的所有前499999个字符?
换句话说,是O(n)或O(1)的f.seek(n,0)?
解决方法:
您需要更具体地了解对象f的类型.
如果f是存储在磁盘上的文件的正常io
module对象,则必须确定是否正在处理:
>原始二进制文件对象
>一个缓冲区对象,包装原始二进制文件
>一个TextIO对象,包装缓冲区
>内存中的BytesIO或TextIO对象
第一个选项只使用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
模块都使用相同的共享实现,如果您在当前读取位置之前寻找一个点,也会从头开始读取(并且没有更大的缓冲区来避免这种情况).
> chunk
module允许在块边界内进行搜索并委托给底层对象.如果基础文件搜索操作是O(1),则这是O(1)操作.
等等,这取决于.