Головоломка для чтения битов (чтение двоичного файла в C ++) - PullRequest
2 голосов
/ 20 февраля 2012

Я пытаюсь прочитать файл train-images-idx3-ubyte, который можно найти здесь вместе с соответствующим описанием формата файла (внизу веб-страницы). Когда я смотрю на байты с 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. То, что я на самом деле хотел прочитать здесь, было 10000. Может быть, у вас есть подсказка?

Ответы [ 2 ]

2 голосов
/ 21 февраля 2012

Как упоминалось в других ответах, вам нужно использовать неформатированный ввод, то есть istream::read(...) вместо operator>>. Перевод приведенного выше кода для использования read read:

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, чтобы разобраться в этом, если вы работаете на базе Intel машина:

samples = ntohl(samples);

, что дает кодировку = 8, размерность = 3, элементы = 60000.

2 голосов
/ 20 февраля 2012

Входные данные отформатированы, что приведет к неправильному считыванию результатов из файла.Чтение с неформатированного ввода даст правильные результаты.

...