使用Python从大型二进制文件中删除字符序列

3 投票
6 回答
4479 浏览
提问于 2025-04-11 20:48

我想在Python中从一个二进制文件中去掉连续的相同值。一个简单的方法就是把文件读进来,然后用re.sub来替换掉那些不需要的连续值。不过,这种方法在处理大文件时就不太好用了。有没有什么办法可以用numpy来实现呢?

6 个回答

1

dbr的解决方案是个好主意,但有点复杂。其实你只需要在读取下一个数据块之前,把文件指针回退到你要查找的序列的长度就可以了。

def ReplaceSequence(inFilename, outFilename, oldSeq, newSeq):
 inputFile  = open(inFilename, "rb")
 outputFile = open(outFilename, "wb")

 data = ""
 chunk = 1024

 while 1:
      data = inputFile.read(chunk)
      data = data.replace(oldSeq, newSeq)
      outputFile.write(data)

      inputFile.seek(-len(oldSequence), 1)
      outputFile.seek(-len(oldSequence), 1)

     if len(data) < chunk:
           break

 inputFile.close()
 outputFile.close()
2

如果你的内存能放下两个副本,那你就可以轻松地复制一个。第二个副本是压缩后的版本。没错,你可以用numpy来处理,但你也可以使用array这个包。此外,你还可以把你的大二进制对象当作一串字节来直接操作。

听起来你的文件可能真的很大,以至于内存放不下两个副本。(你没有提供很多细节,所以这只是个猜测。)你需要分块进行压缩。你会先读取一块数据,对这块数据进行处理,然后再写出去。再次强调,numpy、array或者简单的字节串都可以很好地完成这个任务。

5

如果你的电脑内存不够,无法执行 open("big.file").read() 这个操作,那么使用numpy也没什么用。因为numpy和Python的变量一样,都是用内存的。如果你的电脑只有1GB的内存,那你最多只能加载1GB的数据到numpy里。

解决办法很简单——分块读取文件。你可以用 f = open("big.file", "rb") 打开文件,然后用 f.read(500) 一次读取500个字节。读取完后,把这些内容处理完再写回到另一个文件里。这其实和在C语言中读写文件的方式差不多。

不过,这样做有个问题,就是如果你替换的内容模式错过了,就会出错。例如:

target_seq = "567"
input_file = "1234567890"

target_seq.read(5) # reads 12345, doesn't contain 567
target_seq.read(5) # reads 67890, doesn't contain 567

显而易见的解决办法是,从文件的第一个字符开始,检查 len(target_seq) 个字符,然后向前移动一个字符,再检查一次。

比如(伪代码!):

while cur_data != "":
    seek_start = 0
    chunk_size = len(target_seq)

    input_file.seek(offset = seek_start, whence = 1) #whence=1 means seek from start of file (0 + offset)
    cur_data = input_file.read(chunk_size) # reads 123
    if target_seq == cur_data:
        # Found it!
        out_file.write("replacement_string")
    else:
        # not it, shove it in the new file
        out_file.write(cur_data)
    seek_start += 1

虽然这种方法不是最有效率的,但它能工作,而且不需要在内存中保留文件的副本(或者两个副本)。

撰写回答