C# 在大型二进制文件中搜索字符串

C# 在大型二进制文件中搜索字符串,c#,.net,file-io,C#,.net,File Io,我有一个大的二进制文件(1MB

我有一个大的二进制文件(1MB 编辑:索引文件中的字符串按顺序排序。

如果编码是固定的(ASCII),则相对简单。打开一个二进制流,逐字节读取,并与targetstring的第一个字符匹配

如果字符串使用另一种(UTF-8)编码,那么它会变得更复杂。

如果编码是固定的(ASCII),那么它相对简单。打开一个二进制流,逐字节读取,并与targetstring的第一个字符匹配


如果字符串使用另一种(UTF-8)编码,它会变得更复杂。

按排序顺序(按字符串)存储{string,size,offset}元组,并使用二进制搜索字符串


您还可以在文件的开头存储字符串的每个第一个字母的偏移量。例如,如果文件中以“a”开头的字符串开始于位置120,而以“b”开头的字符串开始于位置2000,则可以以类似于
1202000,…

的方式开始文件,按排序顺序(按字符串)存储{string,size,offset}元组,并对字符串使用二进制搜索


您还可以在文件的开头存储字符串的每个第一个字母的偏移量。例如,如果文件中以“a”开头的字符串开始于位置120,而以“b”开头的字符串开始于位置2000,则可以使用类似于
1202000,…
的内容开始文件。查找。

首先,对文件使用内存映射。它将比将其读入RAM更有效,因为只有一个副本,而不是两个副本(一个在程序中,一个在文件缓存中)

如果每个字符串都是固定长度的,则二进制搜索非常容易,因为可以将内存视为字符数组的数组

如果每个字符串长度可变,但以0结尾,则可以使用二进制搜索的变体,跳转到字符串列表的中间,搜索下一个0,然后测试下一个字符串。然后向前或向后跳转到字符串列表的1/4或3/4并重复

如果每个字符串都是Pascal样式的可变长度字符串,并且在开头有一个字节计数,那么就比较麻烦了。对于不频繁的搜索,从一开始的线性搜索不会太慢。如果要查找精确的字符串匹配,请不要忘记,只需检查长度是否匹配,就可以跳过大多数字符串


如果您必须经常搜索列表,那么构建一个指向字符串列表的字符指针数组将再次使二进制搜索变得非常容易。如果该文件确实是用于快速搜索的索引文件,那么它可能已经在某个地方包含了该文件,除非设计者打算在加载该文件时构建一个字符指针数组。

首先,对该文件使用内存映射。它将比将其读入RAM更有效,因为只有一个副本,而不是两个副本(一个在程序中,一个在文件缓存中)

如果每个字符串都是固定长度的,则二进制搜索非常容易,因为可以将内存视为字符数组的数组

如果每个字符串长度可变,但以0结尾,则可以使用二进制搜索的变体,跳转到字符串列表的中间,搜索下一个0,然后测试下一个字符串。然后向前或向后跳转到字符串列表的1/4或3/4并重复

如果每个字符串都是Pascal样式的可变长度字符串,并且在开头有一个字节计数,那么就比较麻烦了。对于不频繁的搜索,从一开始的线性搜索不会太慢。如果要查找精确的字符串匹配,请不要忘记,只需检查长度是否匹配,就可以跳过大多数字符串


如果您必须经常搜索列表,那么构建一个指向字符串列表的字符指针数组将再次使二进制搜索变得非常容易。如果这个文件确实是一个用于快速搜索的索引文件,那么它可能已经在某个地方包含了这个文件,除非设计者打算在加载文件时构建一个字符指针数组。

我遇到过类似的情况。使用传统的字符串搜索逐字读取(假定为ASCII)。由于您已经有了一个索引文件,我认为您无法进一步提高性能。我遇到过类似的情况。使用传统的字符串搜索逐字读取(假定为ASCII)。由于您已经有了一个索引文件,我认为您无法进一步提高性能。不幸的是,Boyer Moore似乎不值得在C#中实现。“签出”。@Jonathan Wood:如果您可以将整个文件加载到内存并使用
IndexOf
,则不会签出。但是对于流式数据.NET不提供搜索方式,因此建议使用Boyer Moore算法。@Groo:听起来很有趣。想再写一篇文章吗?:-)不幸的是,Boyer-Moore似乎不值得在C#中实现。“签出”。@Jonathan Wood:如果您可以将整个文件加载到内存并使用
IndexOf
,则不会签出。但是对于流式数据.NET不提供搜索方式,因此建议使用Boyer Moore算法。@Groo:听起来很有趣。想再写一篇文章吗?:-)