我有一个二进制数据文件,其中包含各种字符串.我正在尝试编写一个C代码来查找文件中第一次出现用户指定的字符串.(我知道这可以用bash完成,但出于其他原因我需要一个C代码.)现在的代码是:
#include#include #define CHUNK_SIZE 512 int main(int argc, char **argv) { char *fname = argv[1]; char *tag = argv[2]; FILE *infile; char *chunk; char *taglcn = NULL; long lcn_in_file = 0; int back_step; fpos_t pos; // allocate chunk chunk = (char*)malloc((CHUNK_SIZE + 1) * sizeof(char)); // find back_step back_step = strlen(tag) - 1; // open file infile = fopen(fname, "r"); // loop while (taglcn == NULL) { // read chunk memset(chunk, 0, (CHUNK_SIZE + 1) * sizeof(char)); fread(chunk, sizeof(char), CHUNK_SIZE, infile); printf("Read %c\n", chunk[0]); // look for tag taglcn = strstr(chunk, tag); if (taglcn != NULL) { // if you find tag, add to location the offset in bytes from beginning of chunk lcn_in_file += (long)(taglcn - chunk); printf("HEY I FOUND IT!\n"); } else { // if you don't find tag, add chunk size minus back_step to location and ... lcn_in_file += ((CHUNK_SIZE - back_step) * sizeof(char)); // back file pointer up by back_step for next read fseek(infile, -back_step, SEEK_CUR); fgetpos(infile, &pos); printf("%ld\n", pos); printf("%s\n\n\n", chunk); } } printf("%ld\n", lcn_in_file); fclose(infile); free(chunk); }
如果你想知道的话,那back_step
就是处理一个不太可能的事件,即所讨论的字符串是由chunk
边界分割的.
我试图检查的文件大小约为1Gb.问题是,由于某种原因,我可以在前9000个左右的字节中找到任何字符串,但除此之外,strstr
它不会检测到任何字符串.也就是说,如果我在文件中查找超过9000个字节的字符串,strstr
则不会检测到它.代码读取整个文件,从不找到搜索字符串.
我尝试过CHUNK_SIZE
128到50000 不等,结果没有变化.我也尝试过变化back_step
.我甚至放入诊断代码,以便在找不到字符串chunk
时逐个字符地打印出来strstr
,果然,字符串正好在它应该的位置.诊断输出pos
始终是正确的.
谁能告诉我哪里出错了?strstr
这里使用的是错误的工具吗?
由于您说您的文件是二进制文件,因此strstr()
将停止扫描文件中的第一个空字节.
如果您希望在二进制数据中查找模式,那么该memmem()
函数是合适的(如果可用).它可以在Linux和其他一些平台(BSD,macOS,...)上使用,但它没有被定义为标准C或POSIX的一部分.它担负着大致相同的关系strstr()
是memcpy()
熊来strcpy()
.
请注意,您的代码应检测读取的字节数,fread()
并仅搜索该字节数.
char *tag = …; // Identify the data to be searched for size_t taglen = …; // Identify the data's length (maybe strlen(tag)) int nbytes; while ((nbytes = fread(chunk, 1, (CHUNK_SIZE + 1), infile)) > 0) { … tagcln = memmem(chunk, nbytes, tag, taglen); if (tagcln != 0) …found it… … }
你不明白为什么你有+1
块大小.该fread()
函数不会在数据末尾添加空字节或类似的东西.我没有改变这个方面,但可能不会在我自己的代码中使用它.
你需要注意识别跨越两个块之间边界的标记.