使用编码打开内存映射文件

时间:2016-03-25 23:29:07

标签: python python-2.7 python-3.x encoding memory-mapped-files

Memory mapped file是使用正则表达式或对大型二进制文件进行操作的有效方法。

如果我有一个大文本文件(~1GB),是否可以使用编码感知映射文件?
[\u1234-\u5678]这样的正则表达式不适用于bytes个对象,将模式转换为unicode也不起作用(因为"[\u1234-\u5678]".encode("utf-32")例如无法正确理解范围)。
如果我使用str将搜索模式从bytes转换为.encode(),搜索可能会有效,但它仍然有限,应该有一种更简单的方法,而不是整天解码和编码。

我尝试在io.TextIOWrapper内用io.BufferedRandom包装它,但无济于事:

AttributeError: 'mmap.mmap' object has no attribute 'seekable'

创建包装器(使用继承)并设置方法seekablereadablewritable以返回True也不起作用。

关于编码,可以假定固定长度编码,如utf-32,代码点或utf-16的较低BMP(如果它甚至可能仅涉及该部分)。

任何python版本都欢迎使用解决方案。

1 个答案:

答案 0 :(得分:1)

如果不从头开始重新发明轮子(编写re模块的所有新版本,mmap模块等),或编写极其复​​杂的正则表达式,你就无法做到这一点。使用像真正的Unicode字符范围之类的东西的细节(你可以在三种不同的模式之间进行交替来制作[\u1234-\u5678],类似于(?:\x12[\x34-\xff]|[\x13-\x55].|\x56[\x00-\x78]))。

基本上,re模式仅适用于str,或与bytes类似的对象(您无法尝试使用memoryview和强制转换,因为re仍然将其视为字节,而不是更大的类型。)

对于简单搜索,您可以在编码用于搜索的字符串后尝试使用mmap.find,但这仍然容易出现微妙的错误;对于UCS-2或UTF-32,您需要检查find的返回值是否分别在两个或四个字节边界上对齐,以确保您没有误认为一个字符的结尾和开头下一个完全不同的角色。如果对齐测试失败,则必须使用最后一个返回值+ 1的start偏移量重复搜索,直到您获得匹配或find返回-1为止。在一般情况下做这件事并不合理。