2013-04-25 54 views
-3

我想打開並讀取4 MB bin文件, 但我不能使用fread讀取大於700 KB的數據。 其實我想打開並閱讀起始ROM文件 這是二進制格式,讀取應該從開始到最後一個字節。 試圖讀取該數量時,運行時發生錯誤,程序停止並關閉。fread函數只讀取大約700kb

我的代碼:

#include <stdio.h> 
int main() 
{ 
    FILE* fp; 
    int buffer[4000000]; 
    fp=fopen ("file.bin","rb"); 
    fread (buffer,sizeof(int),4000000,fp); 
} 

什麼是錯我的代碼?

+4

你知道平均堆棧大小是否在1到4兆字節之間?你有幾乎16兆字節的堆棧。我很驚訝你的程序甚至加載。 – 2013-04-25 08:15:31

+0

我在C編程中是全新的,如果它可能向我展示如何完成任務,請.. – 2013-04-25 08:19:23

+2

然後這裏有幾個其他有用的提示(與你的問題無關,但仍然很好):在C中從來沒有一個聲明函數時爲空參數列表。這意味着該函數需要一個未指定數量的未指定參數。當用於'main'時,它實際上不符合規範。如果你想要一個沒有參數的函數使用'void',如'int main(void)...'所示。你還聲明'main'返回一個'int'(這是正確的),但你實際上並沒有返回任何東西。你要麼需要調用'exit'或'return'值(零意味着沒有錯誤)。 – 2013-04-25 08:24:14

回答

0

更好的選擇是加載文件我的塊。

另外爲了不用完堆棧,應該使用動態分配的緩衝區,因爲heap大於stack

#define BLOCK_SIZE 4096 

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

int read_file(FILE* file, unsigned char* buffer); 

int main() 
{ 
    FILE* fp; 
    unsigned char* buffer = NULL; 
    int bytes_read = 0; 
    fp=fopen ("file.bin","rb"); 
    bytes_read = read_file(fp, buffer); 
    return 0; 
} 

int read_file(FILE* file, unsigned char* buffer) 
{ 
    int bytes_read = 0; 
    int block_bytes_read = 0; 
    unsigned char block[BLOCK_SIZE]; 

    do 
    { 
     block_bytes_read = fread (block,sizeof(char),BLOCK,file); 
     buffer = realloc(buffer, block_bytes_read*sizeof(char)); 
     memcpy((buffer + bytes_read), block, block_bytes_read*sizeof(char)); 
     bytes_read += block_bytes_read; 
    } while (block_bytes_read != 0); 

    return bytes_read; 

} 
+0

小小的例子可以解決問題,,如何使動態分配的緩衝區 – 2013-04-25 08:34:25

+0

@SaeedBasrah試試這個 – Alex 2013-04-25 08:51:02

+0

謝謝亞歷克斯我簽署了你的答案 – 2013-04-25 08:57:49

3

請在特定塊大小的循環中執行讀取操作。

0

使buffer成爲一個靜態變量,所以它不會駐留在堆棧上。

此外,在循環內部使用fread,因爲它不會一次讀取所有文件。

+0

使緩衝區成爲一個靜態變量,所以它不會駐留在堆棧上?這將是偉大的,但我真的是新的C。 – 2013-04-25 08:35:56

+0

只需在'int buffer [4000000];'之前放置關鍵字'static'即可。 這不是最好的解決方案 - 其他的都給了你更好的解決方案。這是最快的。 – Elazar 2013-04-25 08:39:09

+0

是否有任何證據表明使用'static'存儲持續時間聲明的對象不能位於堆棧上? – Sebivor 2013-04-25 09:48:43

1

[1]缺少返回(返回否定以指示錯誤發生)

[2]使用malloc(動態分配堆外),而不是堆疊

[3]檢查文件讀指針值,存儲器分配&讀取的字節數

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

int main() 
{ 
    FILE * pFile; 
    char * buffer; 
    size_t size = 4194304; 
    size_t result; 

    pFile = fopen ("file.bin" , "rb"); 
    if (pFile==NULL) { 
     fputs ("Unable to open file",stderr); 
     return (-1); 
    } 

    buffer = (char*) malloc (sizeof(char)*size); 
    if (buffer == NULL) { 
     fputs ("Unable to allocate memory",stderr); 
     return (-2); 
    } 

    result = fread (buffer,1,size,pFile); 
    if (result != size) { 
     fputs ("Unable to read 4 MB",stderr); 
     return (-3); 
    } 

    fclose (pFile); 
    free (buffer); 
    return 0; 
} 
+0

'return'語句中不需要括號。 'sizeof(char)'也是不必要的,因爲它總是1,儘管可以說可以幫助可讀性。無論如何,我們都需要+1,1。 – Elazar 2013-04-25 08:51:57

0

我這個代碼最大的問題是在這條線:

fread (buffer,sizeof(int),4000000,fp); 

這條線實際上引入了一個重要的問題列表。首先,不能保證您正在閱讀的文件已成功打開。正如其他人所指出的那樣,您需要比較fpNULL來作出保證。其次,似乎我經常強調這種方式:你真的應該檢查返回值。這適用於所有標準C函數,而不僅僅是fopenfread

返回值fread告訴您有多少項實際上被讀取。假設你要求四百萬int秒,而該文件只包含兩個。返回值會告訴你只有兩個int被讀取。


現在,到大的東西!讓我們首先考慮sizeof(int)在不同的實現上有所不同。您的系統可能會讀取四個字節,而另一個可能讀取兩個字節,但可能讀取八個字節。這只是整數表示可能不同的基本方式。

讓我們考慮一個更微妙的,但同樣的破壞性方式整數表示可能會有所不同:假設你的int s爲四個字節,用最左邊的位是最低顯著位。另一臺機器可能使用最左邊的位作爲至少的重要位。同樣,考慮字節順序排列,這是字節的順序。

假設您的int s是32位,並且它們表示-(1 << 31)(1 << 31)之間的值,這意味着沒有填充位。另一個系統可能會使用具有16位填充的32位整數,這意味着它可能僅表示-(1 << 16)(1 << 16)之間的值。假設這些填充位是奇偶校驗位,以確保RAM正常運行(例如Intel Xeon服務器)。現在你有一種情況,你的服務器告訴你你的內存有問題,如果沒有。

您的代碼應該從您的文件用於存儲整數的整數表示形式顯式轉換爲計算機本機使用的任何表示形式。在將整數寫入文件時,需要確保您明確地將您的實現表示轉換爲表示表示的。同樣,當從文件中讀取整數時,代碼應該明確地將該表示轉換爲您的實現表示。例如,讓我們假設您的int值不會超出-3276732767(16位有符號整數,1的補碼)。使用兩個字節來表示這種情況是可移植的,但您需要明確定義該整數的符號和表示形式。寫入時,可以提取符號和絕對值,然後將sign * 128 + absolute_value/256absolute_value % 256寫入文件。閱讀時,您會提取符號位,然後相乘並添加以重建您的值。


讓我們考慮您的文件據稱是4MB,而你正在閱讀sizeof (int) * 4000000值。 4MB是0x400000,而不是sizeof (int) * 4000000。我想你真的想將沿着線的東西是什麼:

unsigned char *foo = malloc(0x400000); /* 4MB */ 

/* XXX: Handle malloc errors here */ 
assert(foo != NULL); 

FILE *fp = fopen("file.bin", "rb"); 

/* XXX: Handle fopen errors here */ 
assert(fp != NULL); 

size_t num_bytes_read = fread(foo, 1, 0x400000, fp); 

/* XXX: Transform the bytes into integers */ 

free(foo); 

我的問題是,它依賴於一個4MB緩存只讀取和轉換字節爲整數。這個任務根本不需要緩衝區!

FILE *fp = fopen("file.bin", "rb"); 

/* XXX: Handle fopen errors here */ 
assert(fp != NULL); 

for (;;) { 
    int x = fgetc(fp); 

    /* XXX: Handle fgetc errors here */ 
    assert(x >= 0); 

    int y = fgetc(fp); 

    /* XXX: Handle fgetc errors here */ 
    assert(y >= 0); 

    /* XXX: Transform the characters in x and y into the int values */ 
}; 

free(foo); 

無論你需要存儲的地方不是在問題中指定的轉化價值。如果你不需要,那麼我的下一個問題就是使用一個數組,當你只能讀一個項目,處理它,然後移動到下一個項目。

+0

多數民衆贊成在很好的解釋和有益thanx ,,,問題是,我只是真正的初學者在C編程。 – 2013-04-25 09:35:13