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

5

内存映射文件是在处理大型二进制文件时使用正则表达式或进行操作的有效方式。

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

我尝试将其包装在 io.BufferedRandom 中的 io.TextIOWrapper 中,但没有成功:

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

使用继承创建包装器,并将方法 seekablereadablewritable 设置为返回 True 也没有起作用。

关于编码,可以假定使用固定长度编码,例如 utf-32、代码点或者 utf-16 的低BMP(如果仅参考该部分可能是可能的)。

欢迎针对任何 Python 版本提供解决方案。


2
使用像UTF-8这样的可变长度编码,没有办法在不遍历它前面的49999个字符的情况下确定第50000个字符的位置,这破坏了内存映射的目的。你可能会发现一些适用于固定长度编码的解决方案。 - user2357112
@user2357112 想必这可能会带来问题,但为了这个问题的缘故,可以假定一个固定长度,如 utf-16utf-32 或代码点。 - Bharel
2
UTF-16仍然是可变长度的,而且无论如何,问题在于文件的编码,而不是模式的编码。 - user2357112
@user2357112 更新了说明,指定使用utf-32或者utf-16的低BMP(如果只涉及到这一部分的话)进行编码。是的,文件的编码确实是问题所在。 - Bharel
1个回答

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。总之,在一般情况下这并不是一个合理的做法。

正则表达式应该是 (?:\x12[\x34-\xff]|[\x13-\x55].)|(?:\x56[\x00-\x78])。顺便说一下。 - Bharel
@Bharel:你给出的那个模式相当于[\u1234-\u55ff][\u5600-\u5678],对吧?两个不同的类别覆盖不同的范围,而不是一个类别覆盖整个范围。当然,它仍然只适用于大端UCS-2数据;如果是小端,则必须翻转每个交替的内容。 - ShadowRanger
我的错,它将会是相同的。我还忘记了字节顺序。真是一团糟。无论如何,如果你说它不存在,那听起来相当不幸,但我会等待另一个答案。我相信我不是第一个想在文本文件上使用mmap的人(或者至少我希望我不是)。如果在合理的时间内没有其他回应,我会接受这个答案作为我的命运。 - Bharel
1
@Bharel:你不是第一个想到这个的人,因为我知道几年前我也尝试过弄清楚是否可能。 :-) 我尝试了很多方法,但是 mmap 不能做多字节,即使使用memoryview,甚至进行不同大小的 cast,它们仍像带有 re bytes 模式的 bytes,而 re str 模式仅适用于 str(以及 Python2 中的 unicode),而不适用于任意类型。 - ShadowRanger
那么,我想我们都注定要失败了 :-( 或许你应该联系微软的朋友们为我们提供一个智能的编码mmaps的WinAPI :P 我还是会耐心等待奇迹般的答案吧。 - Bharel
@Bharel:欢迎您这样做,但是如果有任何结果,我会非常惊讶。 - ShadowRanger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接