【问题标题】:Finding pattern in large binary file using C or C++?使用 C 或 C++ 在大型二进制文件中查找模式?
【发布时间】:2011-02-18 22:35:35
【问题描述】:

我有一个约 700 MB 的二进制文件(非文本数据);我想做的是搜索在整个文件中随机位置出现的特定字节模式。例如0x? 0x? 0x55 0x? 0x? 0x55 0x? 0x? 0x55 0x? 0x? 0x55 依此类推,按顺序排列 50 个左右字节。我要搜索的模式是两个随机字节的序列,每两个字节出现 0x55。

即以0x55为分隔符搜索文件中存储的表,然后保存表中包含的数据或进行其他操作。

最好的选择是简单地一次遍历每个单独的字节,然后向前看两个字节以查看值是否为 0x55,如果是,则一次又一次地向前看以确认表存在在那个位置?

加载整个东西?寻找?缓冲块,一次搜索一个字节?

使用 C 或 C++ 查看这个大文件并找到模式的最佳方法是什么?

【问题讨论】:

  • 随机字节是不同的还是特定字节的所有重复?这个随机字节可以是 0x55 吗?这是一次性的,还是您必须搜索多个 700Mb 文件才能找到相同的模式?
  • 您希望看到多少个 0x55?
  • 0x55 之间的两个字节可以是任何值,包括 0x55。有几十个表,因此 0x55 将在整个文件中重复多次。
  • @Jerry Coffin:据我所知(我的 atm 没有文件),并非所有表格的大小都相同。但是,我不记得曾经见过小于 50 字节左右的文件。换句话说,我不知道最小大小是多少,但我至少可以说不会有少于 10-20 个条目的表(即 10-20 对以 0x55 分隔的字节)。跨度>
  • @Kyle Lowry:在这种情况下,我会使用类似 Boyer-Moore-Horspool 的变体。从第 20 个和第 21 个字节开始。如果它们都不是 0x55,则再向前移动 20 个字节,依此类推。

标签: c++ c file search design-patterns


【解决方案1】:

对于regular expression 匹配器或deterministic finite automaton 来说,这听起来很不错。这些是专为满足您的要求而设计的强大工具,如果您可以随意使用它们,那么进行此类搜索应该不会有太多麻烦。在 C++ 中,考虑查看 Boost.Regex 库,它应该具有解决此问题所需的所有功能。

【讨论】:

  • 对于单字节搜索字符串来说,DFA 是不是有点矫枉过正?在没有 DFA 或正则表达式引擎的情况下,以线性方式实现搜索是微不足道的。
  • @Billy ONeal- 也许我误读了上述问题,但这看起来不像只是在寻找一个字节(它在寻找特定的字节模式)。我弄错了吗?
  • @Moron:如果这些是令人震惊的问题,您需要检查 C++ 是否适合使用。
  • @BillyONeal:不,以 O(n*m) 的方式实现搜索很简单。或者,换句话说,非正则表达式、非 DFA、朴素的解决方案将花费大约 50 倍的时间,因为搜索字符串大约有 50 个字节长。
  • @Moron:有时你真的有钉子,你应该用锤子。正则表达式专为字符串中的模式匹配而设计。您需要 something 来查找模式,唯一的问题是您将使用什么外部库(正则表达式或其他),或者您将如何自己编写它。
【解决方案2】:

最终对我有用的是 Boyer-Moore-Horspool 算法(由 Jerry Coffin 建议)和我自己的基于表结构和存储数据的算法之间的混合。

基本上,BMH 算法捕获了我正在寻找的大部分内容。显而易见的东西。

但有些表格确实有奇怪的格式,我必须实现一个半智能搜索,查看每个 0x55 后面的数据,并确定它是否可能是 好数据,或者只是随机的垃圾。

奇怪的是,我最终用 PHP 而不是 C++ 实现了它,并将结果直接转储到 MySQL 数据库中进行查询。搜索过程只用了大约 5 分钟或更短的时间,结果基本上很好。我确实得到了很多垃圾数据,但它捕获了我需要的所有数据,并且(据我所知)并没有留下任何好的数据。

【讨论】:

    【解决方案3】:

    加载整个东西?寻找?缓冲块,一次搜索一个字节?

    如果您可以将整个内容加载到内存中,您可能应该使用您的平台提供的内存映射功能。这样,操作系统可以决定是否应该将大部分文件保留在物理内存中(即系统目前有大量空闲 RAM),或者是否应该只在较小的块中工作。

    当然,这只有在您可以将文件放入工作集时才有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 2016-09-30
      • 2021-08-09
      • 2014-06-20
      相关资源
      最近更新 更多