2011-05-23 180 views
16

我想讀取C 1個字節的二進制文件,每次搜索幾個小時後,我仍然無法獲取任何東西,但垃圾和/或seg故障。基本上二進制文件的格式是256個項目的列表,每個項目是1個字節(0到255之間的無符號整數)。我正在嘗試使用fseek和fread跳轉到二進制文件中的「索引」並檢索該值。我目前擁有的代碼:一次讀取一個二進制文件1個字節

unsigned int buffer; 

int index = 3; // any index value 

size_t indexOffset = 256 * index; 
fseek(file, indexOffset, SEEK_SET); 
fread(&buffer, 256, 1, file); 

printf("%d\n", buffer); 

此時此代碼給了我隨機垃圾數和seg錯誤。關於如何讓這個工作正確的任何提示?

+5

一次讀取一個字節的文件會導致大量的I/O開銷。更好的方法是將整個文件讀入一個緩衝區(因爲它只有256字節)並單獨處理存儲在緩衝區中的每個字節。 – titaniumdecoy 2011-05-23 05:42:53

+0

爲什麼不使用fgetc – Dirk 2011-05-23 05:43:36

+2

@titaniumdecoy - 我相信I/O管理器會緩衝現代操作系統上的讀取。 – jww 2015-07-06 05:09:47

回答

16

在你的代碼中,你試圖讀取256個字節到一個int的地址。如果要一次讀取一個字節,請致電fread(&buffer, 1, 1, file);(請參閱fread)。

但是更簡單的解決方案是聲明一個字節數組,然後將它們一起讀取並處理。

+1

緩衝區的類型爲unsigned int。未初始化,所以在fread(&buffer,1,1,file)之後;'你將得到一個24位包含一些隨機值的數字。 – 2011-05-23 05:47:33

+0

的確如此。謝謝。 – MByD 2011-05-23 05:57:26

+0

如何聲明一個字節數組並將它們一起讀取?謝謝! – 2017-01-18 11:15:39

3
unsigned char buffer; // note: 1 byte 
fread(&buffer, 1, 1, file); 

現在是時候閱讀芒我相信。

1

您試圖將256個字節讀入一個名爲「buffer」的4字節整數變量。您正在覆蓋其他數據的下252個字節。

看起來好像buffer應該是unsigned char buffer[256];或者您應該做fread(&buffer, 1, 1, f),在這種情況下buffer應該是unsigned char buffer;

或者,如果你只是想一個字符,你可以只留下bufferint無符號沒有必要的,因爲C99保證了普通int合理的最低範圍),簡單地說:

buffer = fgetc(f); 
0

代碼存在幾個問題。

的原型FREAD是:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 

你已經設置大小爲256(字節)和計數1這很好,這意味着「讀256個字節一個腫塊,推入緩衝區「。

但是,您的緩衝區長度爲2-8個字節(或者至少遠小於256個字節),因此您有一個緩衝區溢出。您可能想使用fred(&緩衝區,1,1,文件)。

此外,你正在寫字節數據到一個int指針。這將在一個endian - ness(實際上是小端),所以你會很好的英特爾架構,並從中學習的壞習慣,將返回並咬你,這些日子之一。

嘗試真正的努力,只寫字節數據到字節組織的存儲,而不是整數或浮點數。

+1

爲什麼'fread'的原型包含'fwrite'? – 2011-05-23 19:32:07

+0

剪切 - 粘貼錯誤。謝謝,修正。 – Vatine 2011-05-24 08:33:45

14

令人困惑的字節int字節的通用術語是無符號字符。大多數字節是8位寬。如果您正在閱讀的數據是8位,則需要在8位讀:

#define BUFFER_SIZE 256 

unsigned char buffer[BUFFER_SIZE]; 

/* Read in 256 8-bit numbers into the buffer */ 
size_t bytes_read = 0; 
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr); 
// Note: sizeof(unsigned char) is for emphasis 

原因讀取所有數據到內存中,以保持I/O流。無論請求數量多少,每個輸入請求都會有一個開銷。一次讀取一個字節,或一次尋找一個位置是最糟糕的情況。

這裏是用於讀取1個字節所需的開銷的一個示例:

Tell OS to read from the file. 
OS searches to find the file location. 
OS tells disk drive to power up. 
OS waits for disk drive to get up to speed. 
OS tells disk drive to position to the correct track and sector. 
-->OS tells disk to read one byte and put into drive buffer. 
OS fetches data from drive buffer. 
Disk spins down to a stop. 
OS returns 1 byte to your program. 

在程序設計中,上述步驟將被重複256次。根據大家的建議,標有「 - >」的行將讀取256個字節。因此,開銷只執行一次而不是256次,以獲得相同數量的數據。

+2

好戲。 – ybakos 2013-04-08 07:29:42

+0

我被告知操作系統實際上在緩衝。無論如何,如果它不,我很確定磁盤控制器有一點緩衝。 – Nolan 2016-06-16 12:26:53

+0

是的,但總是有調用輸入函數的開銷指令;可能包括重新加載指令緩存。爲了提高性能,應該減少這種開銷 - 因此每個請求的更多數據更有效率。 – 2016-06-16 13:41:24

相關問題