我正在尝试阅读文件'train-images-idx3-ubyte',可以找到here以及相应的文件格式说明(位于网页底部)。当我用od -t x1 train-images-idx3-ubyte | less
(十六进制,逐字节)查看字节时,我得到以下输出:
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 :(得分:2)
输入已格式化,这将导致您从文件中读取错误的结果。从未格式化的输入读取将提供正确的结果。
答案 1 :(得分: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格式,因此如果你在intel上运行,你必须通过ntohl传递它才能理解它基于机器:
samples = ntohl(samples);
,其中encoding = 8,dimension = 3,items = 60000。