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

Opening memory-mapped file with encoding

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

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

我试过用 io.TextIOWrapper 将其包裹在 io.BufferedRandom 中,但无济于事:

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

创建包装器(使用继承)并将方法 seekablereadablewritable 设置为 return True 也不起作用。

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

欢迎任何 python 版本的解决方案。

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

基本上,re 模式仅适用于 str,或适用于 bytes 类对象(并且您不能尝试使用 memoryview 来解决它s 和转换,因为 re 仍然将其视为字节,而不是更大的类型)。

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