Чтение файла с разным типом данных, записанных в файл
Суть вопроса:
Имеется файл, записанный в формате 2 байта, 1 байт, 1 байт. Значения в файле всегда положительным (то есть unsigned) и записаны последовательно в одну строку. Требуется провести чтение файла и записать их в вектор. Как это можно реализовать?
Перепробовал уже множество способов, но так и не могу понять, как его корректно прочитать (и структурой пытался, и через переменные, и тд и тп, просто не понимаю свою проблему).
Чтение осуществлял через ifstream, но можно любой вариант использовать. Сам файл представлен в формате txt или dat.
Файл можно представить в виде такой последовательности

Ответы (2 шт):
В комментарий не влезу...
В чем проблема?
unsigned short var1;
unsigned char var2, var3;
ifstream in("....",ios::binary);
for(;;)
{
in.read((char*)&var1,2);
in.read((char*)&var2,1);
in.read((char*)&var3,1);
....
}
Структура — ну, нужна ее корректная упаковка, на байт.
Что тут не так?
Если уж решили читать байты, то надо стиснуть зубы и читать байты.
Байт в C++ - символ без знака. Можно читать просто символы, дальнейшая обработка будет осложнена.
Код ниже сразу читает одну запись в буфер. Затем из байтов конструируются значения. Так сделано потому что читать сразу в unsigned short плохая идея.
// так делать не надо!
unsigned short v1;
ifs.read(reinterpet_cast<char *>(&v1), 2);
unsigned shortможет оказаться длиннее двух байт. Тогда будет неопределённое поведение - в переменной останется мусор.- порядок байтов внутри
unsigned shortможет быть разным. На разных машинах ваш код прочтет разные значения. - если вас беспокоит производительность, то чтение из файла куда медленнее битовых операций при конструировании значений.
- если вы уверены что порядок байтов под контролем и не хотите ничего считать, то читайте прямо в
uint16_t. У него размер ровно два байта - ни больше, ни меньше. Но я вас предупредил. (В комментарии указывают что этот способ опирается на размер байта в восемь бит, а он может отличаться. Ещё одна причина так не делать.)
Код:
#include <climits>
#include <iostream>
#include <fstream>
int main() {
std::ifstream ifs("record", std::ios::binary);
unsigned char buffer[4];
// читайте запись целиком, так проще обработать ошибки, так быстрее
// тут нужно приведение, зато дальше будет проще работать
if (ifs.read(reinterpret_cast<char *>(buffer), sizeof buffer)) {
// конструируем значение из байтов - защита от различного
// порядка байтов на разных компьютерах
unsigned short v1 = buffer[0] | (buffer[1] << CHAR_BIT);
unsigned char v2 = buffer[2];
unsigned char v3 = buffer[3];
std::cout << v1 << ' '
<< static_cast<int>(v2) << ' '
<< static_cast<int>(v3) << '\n';
} else {
// всегда контролируйте успешность чтения!
// не перечесть сколько возникает ошибок из-за чтения после конца файла
std::cerr << "Error reading record\n";
}
}