2016-04-24 150 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