如何在C++中从二进制文件中删除零件

How to delete parts from a binary file in C++

本文关键字:零件 删除 二进制文件 C++      更新时间:2023-10-16

我想使用C++从二进制文件中删除部分。二进制文件大约为5-10 MB。

我想做的事:

  1. 搜索ANSI字符串"something"
  2. 找到这个字符串后,我想删除下面的n个字节,例如下面的1MB数据。我想删除这些字符,而不是用NULL填充它们,从而使文件更小
  3. 我想把修改后的文件保存到一个新的二进制文件中,除了我删除的丢失的n个字节之外,它和原始文件一样

你能给我一些如何最有效地做到这一点的建议/最佳实践吗我应该先将文件加载到内存中吗?

如何有效地搜索ANSI字符串我的意思是,在找到那个字符串之前,我可能必须跳过几兆字节的数据。>>有人告诉我应该在另一个问题中问它,所以它在这里:如何在二进制文件中查找ANSI字符串?

如何有效地删除n个字节并将其写入新文件

好吧,我不需要它是超高效的,文件不会大于10MB,如果它运行几秒钟就可以了。

有许多快速字符串搜索例程的性能比测试每个字符要好得多。例如,当试图找到"某物"时,只需要测试每9个字符。

下面是我为前面的一个问题写的一个例子:代码审查:查找<身体>在非null终止字符str 上进行标签反向搜索

对于一个5-10MB的文件,如果你的系统支持的话,我会看看writev()。因为它足够小,所以把整个文件读入内存。扫描要丢弃的字节。向writev()传递iovec列表(它将只是读取缓冲区和长度的指针),然后您可以在一个系统调用中重写整个修改后的内容。

首先,如果我理解你在"如何高效搜索"小节中的意思,那么如果目标字符串可能在前几兆字节中,你就不能跳过搜索中的几兆字节数据。

至于将文件加载到内存中,如果你这样做了,不要忘记确保内存中有足够的空间容纳整个文件。如果你去使用你的实用程序,发现你想使用的2GB文件无法容纳你剩下的1.5GB内存,你会感到沮丧。

我假设您将把它加载到内存或内存映射中,以进行以下操作。

你确实明确表示这是一个二进制文件,所以这意味着你不能使用普通的C++字符串搜索/匹配,因为文件数据中的null字符会混淆它(过早结束而没有匹配)。相反,您可以使用memchr查找目标中第一个字节的第一个出现,并使用memcmp将接下来的几个字节与目标中的字节进行比较;继续使用memchr/memcmp对扫描整个东西,直到找到为止。这不是最有效的方法,因为有更好的模式匹配算法,但我认为这是一种有效的方法。

要"删除"n个字节,您必须实际将数据移动到这n个字节之后,将整个数据复制到新位置。

如果您真的将数据从磁盘复制到内存,那么在那里操作数据并写入新文件会更快。否则,一旦在磁盘上找到要开始删除的位置,就可以打开一个新文件进行写入,从第一个文件读取X个字节,其中X是指向第一个文件的文件指针位置,并将它们直接写入第二个文件,然后在第一个文件中查找X+n,并从那里到file1的eof执行同样的操作,将其附加到已经放入file2的内容中。