从文件末尾查找抛出不受支持的异常

新手上路,请多包涵

我有这个代码片段,我正在尝试使用 python 从文件末尾向后查找:

 f=open('D:\SGStat.txt','a');
    f.seek(0,2)
    f.seek(-3,2)

这会在运行时抛出以下异常:

 f.seek(-3,2)
io.UnsupportedOperation: can't do nonzero end-relative seeks

我在这里错过了什么吗?

原文由 seriousgeek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 746
2 个回答

从 Python 3.2 及更高版本的 文档 中:

在文本文件中(那些在模式字符串中没有 b 打开的文件),只允许相对于文件的开头查找(例外情况是查找到文件结尾 seek(0, 2) ).

这是因为文本文件在编码后的字节和它们所代表的字符之间没有一一对应关系,所以 seek 无法判断要跳转到文件中的哪个位置移动一定数量人物。

如果您的程序可以处理原始字节,您可以将程序更改为:

 f = open('D:\SGStat.txt', 'ab')
f.seek(-3, 2)

请注意模式字符串中的 b 对于二进制文件。 (另请注意删除了多余的 f.seek(0, 2) 调用。)

但是,您应该知道,在读取或写入文本时添加 b 标志可能会产生意想不到的后果(例如使用多字节编码),并且实际上 会更改读取或写入的数据类型

原文由 jonrsharpe 发布,翻译遵循 CC BY-SA 4.0 许可协议

现有答案 确实 回答了问题,但没有提供 解决方案。

正如评论中所指出的,这个答案是基于未定义的行为并且不处理 UnicodeDecodeError,您可能会遇到 UTF-8 文件。只要您寻找字符的开头,它就可以很好地与 ASCII 和其他固定宽度编码一起使用。请参阅 Philip 的回答,其中包括解决方法和进一步讨论为什么在 UTF-8 中向后查找是一个问题的评论。

来自 readthedocs

如果文件以文本模式打开(没有 b ),只有 tell() 返回的偏移量是合法的。使用其他偏移量会导致未定义的行为。

这得到 了文档 的支持,它说:

在文本文件中(在模式字符串中没有 b 打开的文件),只允许相对于文件开头 [ os.SEEK_SET ] 查找

这意味着如果你有来自旧 Python 的代码:

 f.seek(-1, 1)   # seek -1 from current position

在 Python 3 中它看起来像这样:

 f.seek(f.tell() - 1, os.SEEK_SET)   # os.SEEK_SET == 0

解决方案

将这些信息放在一起,我们可以实现 OP 的目标:

 f.seek(0, os.SEEK_END)              # seek to end of file; f.seek(0, 2) is legal
f.seek(f.tell() - 3, os.SEEK_SET)   # go backwards 3 bytes

原文由 Eric Lindsey 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题