c - 程序不适用于 C 中的大文件

标签 c file fopen

我在 C 中使用以下程序来过滤包含大约 200,000 行的日志文件。但是程序在大约 12000 行后停止响应。任何解释为什么会发生这种情况以及解决方案? 代码在 GCC (windows) 中编译。

PS:代码正确执行并为小文件提供所需的输出。

#include<stdio.h>
#include<string.h>

int check(char *url)
{
    //some code to filter the data and return either 0 or 1 depending upon input
}

int main()
{
    FILE *fpi, *fpo;
    fpi=fopen("access.log","r");
    fpo=fopen("edited\\filter.txt","w");
    char date[11],time[9],ip[16],url[500],temp[3];
    while(!feof(fpi))
    {
        printf(".");
        fscanf(fpi," %s %s %s %s %s %s",date,time,temp,ip,temp,url);
        if(check(url)) 
            fprintf(fpo,"%s %s %s %s %s %s\n",date,time,temp,ip,temp,url);
    }
    fclose(fpi);
    fclose(fpo);
    printf("\n\n\nDONE! :)");
    return 0;
}

最佳答案

输入文件中的某一行可能包含一个字段,该字段大于您传递给 fscanf() 的字符串变量。它可能会导致缓冲区溢出,随后在某处导致无限循环。只是一个猜测。我建议您将 fscanf() 格式字符串中的 %s 分隔为输出字符串变量的最大长度。

例如,这将确保没有缓冲区溢出并且结果字符串终止:

 fscanf(fpi," %10s %8s %2s %15s %49s %2s", date, time, temp, ip, temp, url);
 date[10] = '\0';
 time[8] = '\0'; 
 ip[15] = '\0'; 
 temp[2] = '\0'; 
 url[499] = '\0'; 

此外,您正在读取 temp 两次。后者读取将覆盖前者。这是你想要的吗?

另一个改进,假设输入文件是行终止的,并且每个日志都在单独的行中,是使用 fgets() 来读取一行,然后才使用 sscanf() 在中间缓冲区上。这样您就可以确保没有格式错误超出一行。此外,sscanf 返回读取项目的数量,在您的情况下 - 6。检查返回值会更安全。

关于c - 程序不适用于 C 中的大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8029992/

相关文章:

PHP - 从另一个驱动器打开文本文件

c - 访问冲突读取位置 0x73726573

c++ - 这是编译器编译的顺序

java - 如何解析文件以查找与生成的字符串匹配的字符串?

iphone - Cocoa错误260,文件路径结构

php - 如何从 php ://input 中删除 XML 版本

c - C 中的 HTML 标签检查

c - qsort 比较器函数不会对整个数组进行排序(留下 1 个元素)

c - 没有链接的变量的重新声明

python - 将列表的每个元素附加到文件行的末尾