5

我正在使用来自文件数据的字节数组。我将其打开'r+b',因此可以更改为二进制文件。

Python 3.7 文档中,它解释了 RegExfinditer()可以使用m.start()m.end()来识别匹配的开始和结束。

在问题Insert bytearray into bytearray Python中,答案说可以通过使用切片对 bytearray 进行插入。但是当尝试这样做时,会出现以下错误:BufferError: Existing exports of data: object cannot be re-sized.

这是一个例子:

    pat = re.compile(rb'0.?\d* [nN]')   # regex, binary "0[.*] n"
    with open(file, mode='r+b') as f:   # updateable, binary
        d = bytearray(f.read())         # read file data as d [as bytes]
        it = pat.finditer(d)            # find pattern in data as iterable
        for match in it:                # for each match,
            m = match.group()           # bytes of the match string to binary m
            ...
            val = b'0123456789 n'
            ...
            d[match.start():match.end()] = bytearray(val)

在文件中,匹配项是0 n并且我正在尝试将其替换0123456789 n为插入 9 个字节。使用此代码可以成功更改文件,只是不会增加大小。我究竟做错了什么?这是显示所有非增加文件大小操作的输出,但在插入数字时失败:

*** Changing b'0.0032 n' to b'0.0640 n'
len(d): 10435, match.start(): 607, match.end(): 615, len(bytearray(val)): 8
*** Found: "0.0126 n"; set to [0.252] or custom:
*** Changing b'0.0126 n' to b'0.2520 n'
len(d): 10435, match.start(): 758, match.end(): 766, len(bytearray(val)): 8
*** Found: "0 n"; set to [0.1] or custom:
*** Changing b'0 n' to b'0.1 n'
len(d): 10435, match.start(): 806, match.end(): 809, len(bytearray(val)): 5
Traceback (most recent call last):
  File "fixV1.py", line 190, in <module>
    main(sys.argv)
  File "fixV1.py", line 136, in main
    nchanges += search(midfile)     # perform search, returning count
  File "fixV1.py", line 71, in search
    d[match.start():match.end()] = bytearray(val)
BufferError: Existing exports of data: object cannot be re-sized
4

1 回答 1

2

这是一个简单的案例,很像在迭代期间修改可迭代对象:

  • it = pat.finditer(d) 从 bytearray 对象创建一个缓冲区。这反过来又“锁定”了字节数组对象的大小。
  • d[match.start():match.end()] = bytearray(val)尝试修改“锁定”字节数组对象的大小。

就像在迭代列表时尝试更改列表大小会失败一样,在迭代缓冲区时尝试更改字节数组大小也会失败。

您可以将对象的副本提供给finditer().

有关缓冲区以及 Python 如何在后台工作的更多信息,请参阅Python 文档


另外,请记住,您实际上并没有修改文件。您需要将数据写回文件,或使用内存映射文件。如果您正在寻找效率,我建议后者。

于 2020-08-25T20:02:25.853 回答