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

Posted

技术标签:

【中文标题】程序不适用于 C 中的大文件【英文标题】:Program not working for large files in C 【发布时间】:2011-12-23 05:16:07 【问题描述】:

我在 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 不允许有任何偏差。尝试删除前 12000 行,看看它是否是数据中的问题。还可以尝试增大缓冲区大小。 FWIW,这听起来像是 awk 的工作。 哦,是的,我增加了缓冲区大小及其工作...谢谢 【参考方案1】:

输入文件中的某一行可能包含一个大于您传递给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。检查返回值会更安全。

【讨论】:

您可以使用getline 阅读整行(至少在 Linux 和最近的 POSIX 上;我不知道它是否适用于 Windows)。 getlinefgets 很容易实现,getdelim 甚至可以用getc 手动实现,或者使用fscanf%[。所以关键是,如果一个平台缺少它们,你总是可以插入基于较低级别功能的替代品。 fgets 版本的速度应该和原生的getline 差不多,但是使用getc 肯定会很慢。

以上是关于程序不适用于 C 中的大文件的主要内容,如果未能解决你的问题,请参考以下文章

thinkphp中的大字母的意思

Eclipse 中的 CodeMR Analyzer 不适用于 C/C++ 代码

CSS不适用于包含的PHP文件

优化Scala代码以读取不适合内存的大文件的有效方法

重命名功能不适用于 php 中的文件夹

文件上传选项以从相机拍摄图像或从图库中选择不适用于 Mozilla Firefox 中的 Web 应用程序