我有一个生成一些大型日志文件的应用程序> 500MB。
我在Python中编写了一些实用程序,允许我快速浏览日志文件并查找感兴趣的数据。但是我现在得到一些数据集,其中文件太大而无法将其全部加载到内存中。
因此,我希望扫描文档一次,构建一个索引,然后只将文档的一部分加载到我想要一次查看的内存中。
当我打开一个'文件'时,这对我有用,一次读一行,并用file.tell()存储偏移量。 然后我可以使用file.seek(offset,0)返回文件的该部分。
然而我的问题是我可能在日志文件中有UTF-8,因此我需要使用编解码器模块(codecs.open(<filename>, 'r', 'utf-8')
)打开它们。使用生成的对象,我可以调用seek和tell,但它们不匹配。
我认为编解码器需要做一些缓冲,或者它可能会返回字符数而不是来自tell的字节数?
有解决方法吗?
答案 0 :(得分:2)
如果为true,这听起来像编解码器模块的错误或限制,因为它可能会混淆字节和字符偏移。
我会使用常规open()
函数打开文件,然后seek()
/ tell()
将为您提供始终一致的字节偏移量。无论何时您想阅读,请使用f.readline().decode('utf-8')
。
请注意,使用f.read()
函数可能会使您处于多字节字符的中间,从而产生UTF-8解码错误。 readline()
将始终有效。
这不会透明地为您处理字节顺序标记,但您的日志文件可能无论如何都没有BOM。
答案 1 :(得分:1)
对于UTF-8,您实际上不需要使用codecs.open打开该文件。相反,首先将文件作为字节串读取是可靠的,然后才解码单个部分(在字符串上调用.decode方法)。在行边界处打破文件是安全的;拆分它的唯一不安全的方法是在多字节字符的中间(你可以从字节值&gt; 128中识别出来)。
答案 2 :(得分:1)
如果你看看它是如何在Python 3中完成的,那么在python中使用UTF8的大部分内容都是有意义的。在你的情况下,如果你阅读Dive in Python 3中的Files章节会更有意义。 :http://diveintopython3.org/files.html
但缺点是,file.seek
和file.tell
使用字节位置,而unicode字符可占用多个字节。因此,如果你这样做:
f.seek(10)
f.read(1)
f.tell()
您可以轻松获得17
以外的其他内容,具体取决于您阅读的字符的长度。
答案 3 :(得分:0)
更新:您无法对codec.open()返回的对象进行搜索/告知。您需要使用普通文件,并在读取后将字符串解码为unicode。
我不知道为什么它不起作用,但我无法使其发挥作用。例如,寻求似乎只能起作用一次。然后你需要关闭并重新打开文件,这当然没用。
tell不使用字符位置,但不会显示您在流中的位置(但可能是底层文件对象从磁盘读取的位置)。
所以可能是因为某种潜在的缓冲,你不能这样做。但阅读之后的解雇工作就好了,所以就这样吧。