2012-02-20 82 views
2

我正在嘗試閱讀文件'train-images-idx3-ubyte',其中可以找到here以及相應的文件格式說明(位於網頁底部)。當我看個字節od -t x1 train-images-idx3-ubyte | less(十六進制數,按字節),我得到下面的輸出:位閱讀謎題(閱讀C++中的二進制文件)

adress     bytes 
0000000 00 00 08 03 00 00 ea 60 00 00 00 1c 00 00 00 1c 
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
... 

這是根據1我的預期。但是當我嘗試用C++讀取數據時,我遇到了問題。我做的是這樣的:

std::fstream trainingData("minst/train-images-idx3-ubyte", 
    std::ios::in | std::ios::binary); 
int8_t zero = 0, encoding = 0, dimension = 0; 
int32_t samples = -1; 
trainingData >> zero >> zero >> encoding >> dimension; 
trainingData >> samples; 
debugLogger << "training set image file, encoding = " 
    << (int) encoding << ", dimension = " 
    << (int) dimension << ", items = " << (int) samples << "\n"; 

但是,這幾行代碼的輸出是:

training set image file, encoding = 8, dimension = 3, items = 0 

一切,但情況(項目,樣本)的號碼是正確的。我嘗試讀取下4個字節作爲int8_t,這給了我至少與od相同的結果。我無法想象samples可以是0.我真正想讀的是10,000。也許你有線索?

+0

您使用的格式化輸入,你需要使用格式化的:它如果你在基於Intel的機器上運行輸入。 – ildjarn 2012-02-20 19:42:38

+2

對二進制輸入使用'istream :: read()'或'istream :: get()'或'istreambuf_iterator'。 – 2012-02-20 20:01:00

回答

2

正如其他答案中所述,您需要使用無格式輸入,即istream::read(...)而不是operator>>。翻譯上面的代碼中使用閱讀率:

trainingData.read(reinterpret_cast<char*>(&zero), sizeof(zero)); 
trainingData.read(reinterpret_cast<char*>(&zero), sizeof(zero)); 
trainingData.read(reinterpret_cast<char*>(&encoding), sizeof(encoding)); 
trainingData.read(reinterpret_cast<char*>(&dimension), sizeof(dimension)); 
trainingData.read(reinterpret_cast<char*>(&samples), sizeof(samples)); 

它得到了大多數的方式出現 - 但00 00 ea 60看起來像它在big-endian格式,所以你必須通過再用ntohl作出的意義傳遞

samples = ntohl(samples); 

這給編碼= 8,尺寸= 3,項目= 60000

+0

是的,這完美地解決了我的問題,並且你是正確的關於endian格式。謝謝! – alfa 2012-02-20 20:55:08

2

輸入被格式化,這會導致您從文件中讀取錯誤的結果。從未格式化的輸入中讀取將提供正確的結果。