6

我有一个应用程序会生成一些大于 500MB 的大型日志文件。

我用 Python 编写了一些实用程序,可以让我快速浏览日志文件并找到感兴趣的数据。但是我现在得到一些数据集,其中文件太大而无法将其全部加载到内存中。

因此,我想扫描文档一次,建立一个索引,然后只将文档的部分加载到我想一次查看的内存中。

当我打开一个“文件”时,这对我有用,一次读取一行并使用来自 file.tell() 的偏移量存储偏移量。然后我可以稍后使用 file.seek(offset, 0) 回到文件的那个部分。

但是,我的问题是日志文件中可能包含 UTF-8,因此我需要使用编解码器模块 ( codecs.open(<filename>, 'r', 'utf-8')) 打开它们。对于生成的对象,我可以调用 seek 和 tell 但它们不匹配。

我假设编解码器需要做一些缓冲,或者它可能返回字符计数而不是来自tell的字节?

有没有解决的办法?

4

4 回答 4

3

如果为真,这听起来像是编解码器模块的错误或限制,因为它可能会混淆字节和字符偏移量。

我将使用常规open()函数打开文件,然后seek()/tell()将为您提供始终一致的字节偏移量。每当您想阅读时,请使用f.readline().decode('utf-8').

但请注意,使用该f.read()函数可能会将您置于多字节字符的中间,从而产生 UTF-8 解码错误。readline()将永远有效。

这不会为您透明地处理字节顺序标记,但是您的日志文件可能无论如何都没有 BOM。

于 2009-10-02T15:31:09.733 回答
2

对于 UTF-8,您实际上不需要使用 codecs.open 打开文件。相反,首先将文件作为字节字符串读取是可靠的,然后才解码单个部分(在字符串上调用 .decode 方法)。在行边界处破坏文件是安全的;拆分它的唯一不安全方法是在多字节字符的中间(您可以从其字节值> 128 中识别)。

于 2009-10-02T15:32:08.610 回答
1

如果你看看它在 Python 3 中是如何完成的,那么在 python 中使用 UTF8 发生的大部分事情都是有意义的。在你的情况下,如果你阅读 Dive into Python 3 中的文件一章,它会更有意义:http: //diveintopython3.org/files.html

不过,它的缺点是它可以处理字节位置,file.seekfile.tellunicode 字符可以占用多个字节。因此,如果你这样做:

f.seek(10)
f.read(1)
f.tell()

您可以轻松获得除 之外的其他17内容,具体取决于您阅读的一个字符的长度。

于 2009-10-02T16:03:55.297 回答
0

更新:您不能对 codec.open() 返回的对象进行搜索/判断。您需要使用普通文件,并在读取后将字符串解码为 un​​icode。

我不知道为什么它不起作用,但我不能让它起作用。例如,搜索似乎只工作一次。然后你需要关闭并重新打开文件,这当然没有用。

tell 不使用字符位置,但不会显示您在流中的位置(但可能是底层文件对象在从磁盘读取时的位置)。

所以可能是因为某种底层缓冲,你不能这样做。但是阅读后解码效果很好,所以去吧。

于 2009-10-02T15:36:01.770 回答