在普通文件中搜索字符串

时间:2012-05-15 15:42:42

标签: c linux

在C程序中,我需要在普通文件中搜索确切的字符串(我使用Linux)。我该怎么做才能搜索?

我的第一个假设包括将文件的每一行移动到RAM(通过 fgets()),并在每次移动后检查该行是否是正确的字符串。如果不是,循环将重新调用 fgets()并检查字符串直到EOF。

但是,拥有1.5亿行的文件会发生什么?发现这种顺序搜索似乎根本无效。

但是,我正在考虑使用插入排序进行二元搜索,以便对我的程序添加到文件中的行进行排序(它每隔3秒左右添加一行,在检查到该行之后立即添加一行) t出现在字符串文件中)。但后来我放弃了,因为我首先需要将线路移动到RAM,使用的时间与用于顺序搜索的时间相同。因此我选择了顺序搜索。

这个假设是对的吗?或者,还有更好的方法?我真的希望如此。

4 个答案:

答案 0 :(得分:2)

您可以使用mmap将整个文件映射到内存中,然后进行strnstr搜索:

#include <sys/mman.h>

const char *fileName = "~/test.txt";
long fileLength;

// open file and get it's length
FILE *fptr = fopen(fileName, "r");

if (fptr == NULL || ferror(fptr))
{
    perror("could not open file");
    fclose(fptr);
    return 0;
}

fseek(fptr, 0, SEEK_END);
fileLength = ftell(fptr);
// return to the start of the file
fseek(fptr, 0, SEEK_SET);

// map the file
char *fileData = mmap(NULL, fileLength, PROT_READ, MAP_FILE | MAP_SHARED, fileno(fptr), 0);

if (fileData == MAP_FAILED)
    perror("could not map file");

// scan the file
char stringToSearchFor[] = "this is my string!";
if (strnstr(fileData, stringToSearchFor, fileLength) != NULL)
{
    printf("file contains the string!");
}
else {
    printf("file doesn't contain the string");
}

// clean up our code
munmap(fileData, fileLength);
fclose(fptr); 

答案 1 :(得分:0)

使用mmap将文件映射到内存,然后对其进行标准memmem搜索。您的操作系统将根据需要处理文件。

答案 2 :(得分:0)

您能提供更多信息吗? 普通文件是什么意思? 您需要进行的文件最大大小是什么?

如果它是大文件而您需要执行快速搜索,请按照下一个算法原型进行操作:

  • 创建您的文件索引
  • 在索引中执行搜索
  • 在文件中添加新信息后启动索引过程。(将创建delta索引)
  • 使用当前索引添加delta索引 注意:您需要缓存新信息以提供更好的性能。

您的搜索算法将取决于您将使用的索引类型。(它可能是树木,二叉树等)

有关更多信息,您需要了解索引,搜索索引,存在的开源搜索系统,例如:apache lucene和sphinx。

UPD:这将是有用的链接: Implementing a index for text file content

https://superuser.com/questions/233665/efficient-way-to-index-text-files

答案 3 :(得分:0)

尝试在大数据上匹配字符串时,可以创建快捷方式过滤器来固定该过程。 firefox扩展AdBlock Plus实际上使用此技术来检查传入的页面请求,并将其与大量过滤器匹配。然后它会阻止匹配的过滤器(广告)。但我离题了。

当你将一个字符串与n个文字匹配时,在算法上它需要best case scenario中的O(n)时间 减少匹配字符串的时间消耗的技巧是减小 n 的大小。 快捷方式过滤器的概念是您创建包含在相关字符串中的短模式。这样,您花费较少的时间来检查每个字符串的正确性。如果过滤器匹配字符串,则检查完整字符串。

基本上可以说我有3个字符串:

1)ABCDABCD 2)DCBABCDA 3)ABDEFGHI

假设我有一个模式“ABC”。迭代时,第1和第2个字符串将返回匹配。第三个字符串被拒绝。然后,只检查那些匹配正确字符串模式的字符串。 另一方面。模式“EFG”拒绝1和2(在更短的时间内)并匹配3.

通过使用哈希表可以进一步改善子串的匹配。 在这里,您可以修复子字符串的大小,如上所述。 然后,对于每个字符串,您计算长度为3的所有子字符串的哈希值。这样,您可以快速确定(在O(1)时间内)哪些模式与字符串匹配。