C ++ двоичное чтение файла в структуру - PullRequest
0 голосов
/ 02 декабря 2011

Я написал бинарный файл, используя следующую структуру:

struct block{
char data[32];
};

Итак, в итоге я получаю большой двоичный файл, полный char [32]. Данные отформатированы в определенных позициях, поэтому сбор определенных фрагментов информации не составляет труда. Тем не менее, я попытался прочитать файл так:

int lines=0;
std::ifstream inputFile("file.bin",std::ios::binary);

while (!inputFile.eof())
{
    inputFile.read(blocks[lines].data, sizeof(block));
    lines++;
}

inputFile.close();
lines--;

и затем отображаем это так:

std::cout<<"block 1: "<<blocks[0].data<<std::endl;
// etc ...

Я думал, что block [i] .data должен просто дать мне символ [32], который принадлежит индексу i, но вместо этого он дает мне каждый элемент «данных» в структуре от этого индекса до конца структуры. Я уверен, что это мое недопонимание того, как это работает. Мой вопрос: как мне получить char [32] в виде блоков [i] .data?

Ответы [ 3 ]

2 голосов
/ 02 декабря 2011

Проблема в вашем std::cout выражении вывода. Когда вы пытаетесь вывести blocks[0].data, operator<< получает не массив из 32 символов, а указатель на первый символ. Это интерпретируется как указатель на строку C, и поэтому выводит все символы, найденные в памяти, оттуда до тех пор, пока не найдет '\0'. Поскольку каждый элемент массива содержит только соответствующие символы из файла, выводятся все символы файла (если в файле нет '\0', то вывод на этом останавливается). Кроме того, вам (не) повезло, что '\0' следует за вашими данными в памяти, поэтому вывод на этом останавливается (вместо того, чтобы продолжать выводить то, что находится в памяти впоследствии, и, возможно, выдавать ошибку сегментации, когда конец память процесса достигнута).

Чтобы просто вывести 32 символа в виде символов , используйте std::cout.write(blocks[0].data,32). В противном случае, чтобы вывести их как целые, просто переберите их и конвертируйте каждый в int:

for (int i = 0; i < 32; ++i)
  std::cout << static_cast<int>(blocks[0].data[i]) << ' ';

Конечно, вы можете использовать все потоковые манипуляторы для получения чисел в нужной форме (например, std::hex для шестнадцатеричного вывода и / или std::setw и std::setfill для получения чисел фиксированной ширины).

1 голос
/ 02 декабря 2011

Ваш входной раздел должен быть изменен:

while (inputFile.read(blocks[lines].data, sizeof(block))
{
     lines++;
}

Причина в том, что условие EOF не определяется до тех пор, пока ПОСЛЕ не произойдет операция чтения. Одним из побочных эффектов использования проверки EOF является то, что может быть прочитана дополнительная строка.

1 голос
/ 02 декабря 2011
std::cout<<"block 1: "<<blocks[0].data<<std::endl;

Вы отправляете char[] в поток, который переводится в char*, поэтому он думает, что это строка с нулевым символом в конце, и пытается отобразить его как таковой.Трудно сказать, что вы хотите, но это будет отображаться в шестнадцатеричном формате:

std::cout << std::setfill('0') << std::hex;
for(int i=0; i<25; ++i)
    std::cout << std::setw(2) << blocks[0].data[i];
std::cout << std::setfill(' ') << std::dec;
...