2012-10-15 27 views
2

我想讀取由30e6個位置組成的大的二進制文件,每個文件都有195個雙打。 由於文件太大而無法全部讀入內存,因此我正在以10000個位置的塊讀取它。然後我做了一些計算,並閱讀下一個塊... ...fread有時會返回大於4GiB的文件的錯誤值

因爲我需要隨機訪問該文件,我寫了一個函數來從文件和商店讀取給定的塊(無符號整數塊)它在** chunk_data中。該函數返回讀取的位置總數。

unsigned int read_chunk(double **chunk_data, unsigned int chunk) { 
    FILE *in_glf_fh; 
    unsigned int total_bytes_read = 0; 

    // Define chunk start and end positions 
    unsigned int start_pos = chunk * 10000; 
    unsigned int end_pos = start_pos + 10000 - 1; 
    unsigned int chunk_size = end_pos - start_pos + 1; 

    // Open input file 
    in_glf_fh = fopen(in_glf, "rb"); 
    if(in_glf_fh == NULL) 
     error("ERROR: cannot open file!"); 

    // Search start position 
    if(fseek(in_glf_fh, start_pos * 195 * sizeof(double), SEEK_SET) != 0) 
     error("ERROR: cannot seek file!"); 

    // Read data from file 
    for(unsigned int c = 0; c < chunk_size; c++) { 
     unsigned int bytes_read = fread ((void*) chunk_data[c], sizeof(double), 195, in_glf_fh); 
     if(bytes_read != 195 && !feof(in_glf_fh)) 
      error("ERROR: cannot read file!"); 
     total_bytes_read += bytes_read; 
    } 

    fclose(in_glf_fh); 
    return(total_bytes_read/195); 
} 

的問題,閱讀一些大塊之後,fread()開始給錯誤的價值觀! 此外,根據不同的塊大小,其中fread()開始表現的立場不同,很奇怪:

chunk of 1 pos, wrong at chunk 22025475 
chunk of 10000 pos, wrong at chunk 2203 
chunk of 100000 pos, wrong at chunk 221 

任何人有什麼可能會在任何想法?

+0

什麼是'的sizeof(int)的'上你的平臺? –

+1

問題的標題應該是有意義的。它將幫助用戶總結您的問題。 –

+0

你已經爲塊分配了內存? –

回答

4

確定30e6 positions不是十六進制,而是30,000,000:考慮fseek()的問題:該文件有46,800,000,000字節。普通香草fseek()(在16位和32位平臺上)僅限於前2^32-1個字節(= 4,294,967,295)。

根據程序運行的平臺,您可能必須使用lseek64或其等價物。在Linux中,有

  • 使用lseek()

    的#define _FILE_OFFSET_BITS 64

  • llseek()

  • lseek64()

+0

普通香草'fseek'的限制取決於平臺;在許多平臺上,它將是2 * 64(減一些epsilon)。另一方面,大多數平臺仍然有32位整數,他正在做'int'(或'unsigned int')中的所有算術,這會溢出。 –

+0

@JamesKanze:是的。我已經完成了我的判決。 – wallyk

+0

使它成爲2^31 - 1,但是,offset參數是一個「long」。 –