2012-10-27 48 views
1

我是一個c程序員,試圖開始我的生活在c + +的新階段(我知道我仍然使用下面的printf,但那是因爲格式化非常簡單)。我正在尋找從對象的成員函數打印數據文件的第一個字節。我認爲我的流緩衝在我讀取數據之前就被破壞了,但我失去了做什麼。在C++中通過類讀取二進制數據與streambuf

我的類看起來像下面

class MyParser { 
    MyParser(string filepath); 
    void readHeader(); 

    streambuf *pbuf; 
    long size; 
} 

我的構造函數打開文件,從得到緩衝,輸出的第一個字節,並返回。 (我認爲pbuf在這段代碼的最後會死掉)。此代碼輸出First Byte (in constructor): 0x8C

MyParser::MyParser(string filepath) { 
    ifstream file(filepath.c_str(), ios::in | ios::binary) 
    pbuf = file.rdbuf(); 
    size = pbuf->pubseekoff(0,ios::end,ios::in); 
    pbuf->pubseekpos(0,ios::in); 

    unsigned char byte = pbuf->sgetc(); 
    printf("First Byte (in constructor): 0x%02X\n", byte); 

    return; 
} 

我讀頭被傾倒的第一個字節,但是基於輸出都是看到的是First Byte (in readHeader): 0xFF

void MyParser::readHeader() { 
    unsigned char byte = pbuf->sgetc(); 
    printf("First Byte (in readHeader): 0x%02X\n", byte); 
} 

我主要只是簡單地創建一個解析器,並試圖readHeader

void main() { 
    MyParser parser("../data/data.bin"); 
    parser.readHeader(); 
} 

我認爲我的問題的解決方案是創建一個new streambuffer但new streambuf(file.rdbuf())不工作fo我。有什麼建議?

+0

您爲什麼使用緩衝器來代替['seekg'](http://en.cppreference.com/w/cpp/io/basic_istream/seekg)/ ['tellg'](HTTP: //www.cppreference.com/w/cpp/io/basic_istream/tellg)和['read'](http://en.cppreference.com/w/cpp/io/basic_istream/read)函數[ istream'](http://en.cppreference.com/w/cpp/io/basic_istream)類? –

+0

我在這裏的例子如下:http://www.cplusplus.com/reference/iostream/ifstream/rdbuf/ – Jon

回答

1

您的程序有未定義的行爲:您保留的流緩衝區由您在構造函數的主體中打開的std::ifstream擁有。當這個對象死亡時,流緩衝區也被釋放。避免此問題的最簡單方法是讓您的std::ifstream成爲您班級的成員:這會將流的生命週期與您的對象綁定在一起。使用接口進行解析也可能更容易,而不是有點尷尬的接口。

如果您確實想使用流緩衝區,則可以直接使用new filebufopen()分配std::filebuf。要保留一個指針,你可能會使用std::unique_ptr<std::filebuf>(或者如果你沒有使用C++ 2011,則使用std::auto_ptr<std::filebuf>)。使用指針類安排對象的自動釋放。當然,這些指針仍然是你班級的成員,以獲得正確的人生。

您嘗試複製流緩衝區不起作用,因爲流緩衝區不可複製。你需要直接創建文件緩衝區:

MyParser::MyParser(std::string const& filename) 
    : pbuf(new std::filebuf) 
{ 
    this-pbuf->open("whatever", std::ios_base::in); 
    ... 
} 
+0

謝謝。保持filestream爲成員,並在init列表中打開文件。我正在嘗試寫一些最終會從二進制網絡數據流中讀取二進制數據的東西,所以我覺得將整個緩衝區讀入內存將需要更多的更改。 – Jon

0

你需要一些新的C++教材,因爲(抱歉),但這是錯的。你需要聲明文件流是一個成員,在這個程序中沒有任何地方需要任何new,幾乎沒有人需要處理streambuf

class MyParser { 
    std::ifstream file; 
public: 
    MyParser(string filepath) { 
     file.open(filepath, std::ios::in | std::ios::binary); 
     char byte; 
     file.read(sizeof(byte), &byte); 
     printf("First Byte (in constructor): 0x%02X\n", byte);   
    } 
    void readHeader() { 
     char byte; 
     file.read(sizeof(byte), &byte); 
     printf("First Byte (in readHeader): 0x%02X\n", byte); 
    } 
}; 
+0

參數向後讀取,應該是指針,大小不是大小,指針。 – Christopher