2012-08-24 225 views
0

我必須將數字數據寫入二進制文件。由於我處理的一些數據向量可能會有幾個演出,我學會了不使用C++ iostream。相反,我想使用C文件*。我遇到了一個問題,我需要將一些元數據寫入二進制文件的前面。由於一些元數據一開始並不知道,因此我需要將元數據追加到文件中的適當偏移處。追加二進制文件

例如,可以說我必須輸入uint16_t表示年,月和日,但首先我需要跳過第一個條目(爲精度uint32_t值);

我不知道我在做什麼錯,但我似乎無法追加與「ab」的文件。 下面是我寫的一個例子:

#include<cstdio> 

uint16_t year = 2001; 
uint16_t month = 8; 
uint16_t day = 23; 

uint16_t dateArray[]={year , month, day}; 

File * fileStream; 
fileStream = fopen("/Users/mmmmmm/Desktop/test.bin" , "wb"); 

if(fileStream){ 

// skip the first 4 bytes 
fseek (fileStream , 4 , SEEK_SET); 

fwrite(dateArray, sizeof(dateArray[0]) ,(sizeof(dateArray)/sizeof(dateArray[0])), filestream); 

fclose(filestream); 

} 
// loops and other code to prepare and gather other parameters 

//現在追加與精度的文件的前面。

uint32_t precision = 32; 

File *fileStream2; 
fileStream2 = fopen("/Users/mmmmmm/Desktop/test.bin" , "ab"); 

if(fileStream2){ 

// Get to the top of the file 
rewind(fileStream2); 

fwrite(&precision, sizeof(precision) , 1 , fileStream2); 

fclose(fileStream2); 

} 

附加的數據不寫入。如果我將其更改爲「wb」,則會覆蓋文件。我能夠使它與「r + b」一起工作,但我不明白爲什麼。我認爲「ab」是適當的。另外,我應該使用緩衝區還是這是一個足夠的方法?

謝謝你的提醒

順便說一句,這是MacOSX上

+0

你爲什麼選擇不使用'iostream' –

+0

你可以追加到文件 – CyberDem0n

+1

@科爾約翰遜方式太慢。 C文件吸菸基準測試iostream – Miek

回答

1

由於硬盤驅動器和文件系統的工作方式,將字節插入到文件中間非常緩慢,應該避免這種情況,尤其是在處理多GB文件時。如果您的元數據存儲在一個固定大小的頭文件中,在開始處理其他數據之前,請確保有足夠的空間。如果標題大小可變,則將標題分塊。將1k的標題空間放在開頭,並保留8個字節,以保留到下一個標題塊的偏移值,或者對於EOF爲0。然後,當該塊被填滿時,只需在文件末尾添加另一個塊並將其偏移量寫入前一個頭。

至於技術IO,根據您的需要,使用fopen()模式r+b,w+ba+b。他們都表現出同樣的微小差異。 r+b從第一個字節開始讀取和寫入文件。如果該文件不存在,則會出錯。w+b也會這樣做,但如果文件不存在,請創建該文件。 a+br+b相同,但是它始於文件末尾的文件指針。

您可以使用fseek()rewind()導航文件。 rewind()將文件指針移回文件的開頭。 fseek()將文件指針移動到指定位置。你可以閱讀更多關於它here.

+3

a + b與r + b不一樣。如果文件不存在,a + b將創建它,r + b將失敗。另外,a + b在開始讀取時定位文件,但所有寫入都添加到文件結尾。 [看這裏](http://www.cplusplus.com/reference/clibrary/cstdio/fopen/) –

+0

好吧。我只需要將文件的開頭追加頭部信息幾次。一旦我找到實際處理數字數據的代碼,它都是順序的,我不會嘗試按順序訪問任何內容。當我完成時,我可能不得不添加一些最終的標題信息。而已。 – Miek

+0

謝謝@Alec Danyshchuk;你提供了一個鏈接,明確說明將做我想做的唯一模式的文檔是「r +」或「r + b」。 – Miek

1

「R + B」意味着你可以讀取和寫入到文件中的任何位置。在第二個代碼塊中,rewind()調用將當前位置設置爲字節0,並在此位置完成寫入。

如果您使用「a + b」,這也意味着讀取和寫入訪問,但寫入全部位於文件的末尾,因此您不能在字節0處定位,除非創建了新的空文件。

要重新訪問特定字節的文件,只需使用fseek()即可。 (fileStream,0,SEEK_SET);以及fseek(fileStream,0,SEEK_SET); - 位置精度值

fseek(fileStream,4,SEEK_SET); - 位置到年的值

fseek(fileStream,8,SEEK_SET); - 位置到月份的值

fseek(fileStream,12,SEEK_SET); - 對當天值的位置

+0

我想我只是試圖使用錯誤的模式。謝謝 – Miek