2016-04-24 147 views
2

我需要从文件中读取4000行,对它们进行一些操作,然后读取下一行4000行,对它们进行一些操作,然后读取下一行4000行直到某个BIG文件结束。如何正确执行此操作?从文件中逐行逐行读取C

这是我的基本代码这是刚刚读取的所有行,但是从文件中不逐块:

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

#define bufSize 1024 

int main(int argc, char *argv[]) 
{ 
    FILE* fp; 
    char buf[bufSize]; 
    if (argc != 2) 
    { 
     fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]); 
     return 1; 
    } 
    if ((fp = fopen(argv[1], "r")) == NULL) 
    { /* Open source file. */ 
     perror("fopen source-file"); 
     return 1; 
    } 

    while (fgets(buf, sizeof(buf), fp) != NULL) 
    { 
     buf[strlen(buf) - 1] = '\0'; /* eat the newline fgets() stores */ 
     printf("%s\n", buf); 
    } 
    fclose(fp); 
    return 0; 
} 
+0

关于这一行:'buf [strlen(buf) - 1] ='\ 0';',这不是一个简单的方法,有两种方法可以失败:1)行长度大于1023字节2)文件的最后一行没有以换行符结束。建议:'char * newline = NULL; if(newline = strstr(buf,“\ n”)){* newline ='\ n'; }' – user3629249

回答

1

确定,然后在堆上分配的二维阵列和申报size_t类型的变量n以跟踪行数。请尝试以下操作:

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

#define bufSize 1024 

int main(int argc, char *argv[]) 
{ 
    FILE* fp; 
    if (argc != 2) 
    { 
     fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]); 
     return 1; 
    } 
    if ((fp = fopen(argv[1], "r")) == NULL) 
    { /* Open source file. */ 
     perror("fopen source-file"); 
     return 1; 
    } 

    size_t n = 0; 
    char(*buf)[bufSize] = malloc(bufSize * 4000); 
    if (!buf) { 
     fprintf(stderr, "Error - Failed to allocate memory.\n"); 
     fclose(fp); 
     return 1; 
    } 
    while (1) 
    { 
     if (fgets(buf[n], bufSize, fp) != NULL) { 
      n++; 
      if (n == 4000) { 
       /* do something */ 
       // ... 
       n = 0; 
      } 
     } 
     else { 
      // do something with leftover 
      break; 
     } 
    } 
    free(buf); 
    fclose(fp); 
    return 0; 
} 
+0

感谢您的回答,但它适用于错误 –

+0

有哪些错误?你能详细说明吗? –

+0

此答案不处理源文件不是4000行的偶数倍的情况。另外,在退出程序之前,答案未能将分配的内存传递给'free()'。 – user3629249

2

问题是什么?

您需要使用2个循环。外层人员会重复读取大块的行,直到EOF。

的代码可能看起来像下面的草图:

... 
while (1) 
{ 
    /* read <= 4000 lines and process */ 
} 

内会读取行并将其存储远:

size_t lines = 0; /** next index to be used with lineBuffer 
        (and number of lines already stored)*/ 
char *lineBuffer[4000]; 
char buf[bufSize]; 

while (lines < 4000 && fgets(buf, sizeof(buf), fp) != NULL) 
{ 
    buf[strlen(buf) - 1] = '\0'; 
    lineBuffer[lines] = malloc(strlen(buf); 
    strcpy(lineBuffer[lines], buf); 
    lines++; 
} 

if (lines == 0) 
{ 
    break; /* we are done*/ 
} 
/* do processing on data */ 

/* deallocate dynamic memory */ 
for (int i = lines - 1; lines>=0; i--) 
{ 
    free(lineBuffer[i]); 
} 

lines = 0; 

当然你可以使用静态分配的内存使用

char lineBuffer[4000][bufSize]; 

而不是mallocing。这将节省alloc/dealloc序列,或者使用calloc(400*bufSize); 在顶层(在循环外部)进行分配。但是,考虑到总共大约4MB的内存与当前设置一起使用,这可以留给个人首选项。

关于性能:
静态分配内存可能会带来一些速度优势。
您也可以尝试通过标准输入输出(用于增加缓冲区大小由setbuffer()变种,从文件中读取较大的块。

不管这会不会有什么noticable效果受你应该采取一些性能次测量(如果在一个问题第一个地方)

+0

以外的行:'int line = 0;'应该声明'lines'而不是'line',我建议这一行实际上是:'size_t lines = 0;'发布的答案非常好 – user3629249

+0

@ user3629249:thank你指出问题,相应地编辑答案。 – rpy