2012-02-20 174 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

输入被格式化,这会导致您从文件中读取错误的结果。从未格式化的输入中读取将提供正确的结果。