是否有一个快速的Java库来搜索字符串及其在文件中的位置



我需要搜索大量文件(即600个文件,每个文件0.5 MB)来查找特定的字符串。

我使用的是Java,所以我更希望答案是一个Java库,或者在最坏的情况下,一个我可以从Java调用的不同语言的库。

我需要搜索来返回找到的字符串在文件中的确切位置(因此,例如Lucene似乎是不可能的)。

我需要搜索尽可能快。

编辑开始:

这些文件可能有不同的格式(如EDI、XML、CSV),有时包含非常随机的数据(如数字ID等)。这就是为什么我初步排除了基于索引的搜索引擎。

文件将被多次搜索相似但不同的字符串(即ID可能具有相似的长度和格式,但通常不同)。

编辑结束

有什么想法吗?

600个0.5 MB的文件约为300MB,这在当今很难被视为,更不用说了。在任何现代计算机上进行简单的字符串搜索实际上都应该比CPU更受I/O限制——我的系统上的一个线程可以在1.5秒内搜索300MB的相对简单的正则表达式——如果文件已经存在于操作系统缓存中,则会降到0.2。

考虑到这一点,如果你的目的是不经常执行这样的搜索,那么使用某种索引可能会导致过度设计的解决方案。从迭代所有文件开始,逐块或逐行读取每个文件并进行搜索——这很简单,几乎不值得拥有自己的库。

设置您的性能要求,分析您的代码,验证实际的字符串搜索是否是瓶颈,然后决定是否需要更复杂的解决方案。如果你确实需要更快的东西,你应该首先考虑以下解决方案,按照复杂性的顺序:

  • 使用现有的索引引擎,如Lucene,为每个查询过滤掉大部分文件,然后显式地在剩余的文件中(希望是少数)搜索字符串。

  • 如果你的文件不是真正的文本,所以基于单词的索引可以工作,那么对文件进行预处理,为每个文件提取一个术语列表,并使用DB创建自己的索引系统——我怀疑你会发现FTS引擎使用单词以外的任何东西进行索引。

  • 如果您真的想将搜索时间减少到最低限度,请从文件中提取术语/位置对,并在数据库中输入这些。您可能仍然需要通过查看实际文件进行验证,但速度会快得多。

附言:你根本没有提到我们正在讨论的字符串之王。它是否包含分隔的术语,例如单词,或者您的文件是否包含随机字符?搜索字符串可以用有意义的方式分解成子字符串吗?还是一堆字母?你的搜索字符串是固定的,还是也可以是一个正则表达式?这些问题的答案可能会大大限制什么是实际可行的,什么不是实际可行的——例如,索引随机字符串可能根本不可能。

编辑

从问题更新来看,术语/令牌的概念似乎是普遍适用的,而不是例如在二进制文件中搜索完全随机的序列。这意味着可以索引这些术语。通过在索引中搜索搜索字符串中存在的任何令牌,可以显著减少需要查看实际文件的情况。

  1. 你可以保留一个term->file索引。如果大多数术语对每个文件都是唯一的,那么这种方法可能会提供很好的复杂性/性能权衡。从本质上讲,你会将搜索范围缩小到一两个文件,然后只对这些文件执行完整搜索。

  2. 你可以保留一个term->file:position索引。例如,如果您的搜索字符串是"Alan Turing"。您将首先在索引中搜索令牌"Alan"one_answers"Turing"。你会得到两个文件和职位的列表,你可以相互参照。例如,通过要求令牌"Alan"的位置在令牌"Turing"的位置之前最多30个字符,您将在文件中获得一个可以明确验证的候选位置列表。

我不确定现有的索引库在多大程度上会有所帮助。大多数都是针对文本索引的,可能会错误处理其他类型的标记,如数字或日期。另一方面,你的情况也没有根本的不同,所以你可能可以使用它们——如果必要的话,通过预处理你提供给它们的文件,使它们更容易接受。根据您的需求构建自己的索引系统似乎也不太困难。

你还没有提到你的搜索字符串是否有任何灵活性。你希望能够搜索正则表达式吗?搜索字符串应该是逐字逐句找到的,还是只需要找到其中的术语?空白有关系吗?条款的顺序重要吗?

更重要的是,您还没有提到在您的文件中是否有任何类型的结构需要在搜索时加以考虑。例如,您是否希望能够将搜索限制在XML文件的特定元素?

除非你有SSD,否则你的主要瓶颈将是所有文件访问。不管你在Java中做什么,读取文件大约需要10秒。

如果你有一个SSD,读取文件不会有问题,Java中的CPU速度会更重要。

如果你能为文件创建一个索引,这将有很大帮助。

最新更新