2013-03-26 108 views
0

我在這裏很新的,我有一個問題 我有一個結構,讓我們說整體大小爲8個字節,這裏的結構:C++解析數據字節到結構

struct Header 
{ 
    int ID;    // 4 bytes 
    char Title [4];  // 4 bytes too 
}; // so it 8 bytes right? 

和我有一個文件8個字節的太... 我只是想問一下,如何解析的文件數據到我已經試過這一個是

的結構:

Header* ParseHeader(char* filename) 
    { 
     char* buffer = new char[8]; 
     fstream fs(filename); 

     if (fs.is_open() != true) 
      throw new exception("Couldn't Open file for Parsing Header."); 

     fs.read(buffer, 8); 

     if (!fs) 
     { 
      delete[] buffer; 
      throw new exception("Couldn't Read header OJN file.\nHeader data was corrupted"); 
     } 

     Header* header = (Header*)((void*)buffer); 
     delete[] buffer; 
     fs.close(); 

     return header; 
    } 

但它失敗,並返回我無效的數據比我所期望的(我可以讓你確定,這不是文件錯誤,文件結構正確)

有人可以幫我嗎? 感謝

回答

1

好像你做的一切正常,直到這一點:

Header* header = (Header*)((void*)buffer); 
delete[] buffer; 
fs.close(); 

通知您刪除緩衝區鑄造後,即頭球點到已刪除的位置 - >垃圾,你需要或者不刪除或者如果您仍想使用它,請複製數據。

此外,相當誠實,我不明白你的代碼是如何編譯,你的功能狀態,它返回一個頭,當你返回頭* ..

+0

謝謝,它幫助我 – SirusDoma 2013-03-26 07:23:18

0

您刪除正在被返回的數據。因此header不再可訪問。

我覺得你的意思行是:

Header header = *(Header*)((void*)buffer); 

這實際上將複製的標題。

+0

你能解釋一下嗎? – Kyurem 2013-03-26 07:19:50

0

就C++而言,8字節文件正確映射到struct Header這一事實只是運氣。該結構可以具有內部填充,使其大於8個字節,並且數據的字節順序可能會與您的文件和CPU不同。

我知道你的代碼工作您的特定編譯器版本,在操作系統你的CPU但你不應該進入編碼像的習慣,否則你可能會陷入大隻要你改變任何這些參數(或者甚至可能只是一些編譯器標誌),都會遇到麻煩。換句話說,你在做什麼是極壞練習。在C++中,你甚至不能保證int實際上是4個字節。

從文件加載這些二進制數據的正確方法是單獨加載每個字段並根據您使用的CPU(例如通過hton*/ntoh*或類似函數)確保正確的字節序轉換。使用像int32_t這樣的固定尺寸類型也有幫助。

0

只要定義你的結構在1字節邊界爲:

#pragma pack(1) 
struct Header 
{ 
    int ID;    // 4 bytes 
    char Title [4];  // 4 bytes too 
}; 
#pragma pack() 

首先pack聲明指示編譯器在結構上使用一個字節填充的成員。這種方式的大小爲Header將是8個字節。第二條pack聲明指示回到默認設置。您可能需要使用pushpop指令(請參閱enter link description here) - 但這不是您必需的。

其次,更重要的是,您不應該使用像8這樣的硬編碼值。始終使用sizeof來讀取或寫入結構。而且,絕對不需要這樣的說法:

char* buffer = new char[8]; 
... 

只是聲明Header變量本身,並在其上寫着:爲答案

Header header; 
... 
fs.read(&header, sizeof(Header));