чтение вектора структур из файла

363
08 мая 2017, 02:31

есть структура

struct Record
{
      int Score;
      UnicodeString Name;
};

есть вектор

    std::vector<Record> list;

код для записи структуры в файл

std::ofstream out("output.txt", std::ios::out | std::ios::binary);
std::vector<Record>::size_type size = list.size();
out.write((char*)&list, sizeof(size));
out.write((char*)&list[0], list.size() * sizeof(Record));
out.close();

код для чтения

std::ifstream is("output.txt", std::ios::in | std::ios::binary);
std::vector<Record>::size_type size = 0;
is.read((char*)&size, sizeof(size));
list.resize(size);
is.read((char*)&list[0], list.size() * sizeof(Record));
is.close();

проблема в том что данные либо не записываются(хотя в файле есть изменения, но т.к. он бинарный сложно определить что записалось), либо не читается(что вероятнее т.к. новый вектор имеет размер 0)

UnicodeString - тип строки(все компоненты обычно в текстовых свойствах принимают/возвращают данный тип). Проект делаю в RAD Studio 10.2

Answer 1

Вы все делаете не правильно.

Во-первых здесь вы записываете не размер, а первые sizeof(size) байтов объекта list:

out.write((char*)&list, sizeof(size));

видимо имелось в виду:

out.write((char*)&size, sizeof(size));

К стати, называть объект вектора именем list, мягко скажу, не удачная идея.

Во-вторых, запись и чтение самих элементов у вас так же не правильная. Разберем ваше выражение:

out.write((char*)&list[0], list.size() * sizeof(Record));
  1. (char*)&list[0] здесь вы получаете указатель на первый элемент массива и приводите его к указателю на char, к стати если выше вы не проверяете размер вектора и если он окажется пустым, то здесь бросится исключение;
  2. list.size() * sizeof(Record) определяете размер массива в байтах, это правильно;
  3. поток записывает в файл непрерывный блок байтов размером list.size() * sizeof(Record) начиная с адреса list.size() * sizeof(Record), при этом берутся непосредственно "сырые" байты прямо из памяти без разбора класс не класс, массив не массив;

При этом, поле Score запишется корректно потому, что оно имеет простой числовой тип. А вот поле Name запишется не так как вы, видимо, ожидаете. Запишется побайтовая копия непосредственно полей объекта UnicodeString, а не байты строки. Объект UnicodeString не содержит в себе байты строки, а только указатель на память где они лежат.

Чтобы корректно записать UnicodeString нужно получить указатель на блок памяти где непосредственно хранится строка (делается это с помощью функции UnicodeString::data()), корректно вычислить размер строки в байтах, и в таком виде записывать. Отдельно нужно обрабатывать пустые строки.

Чтение нужно делать в обратном порядке: вычитываете байты строки в промежуточный буфер, а потом передаете этот буфер в конструктор UnicodeString.

READ ALSO
Задача на разности

Задача на разности

Всем привет ! Есть такая задача она проходит 50%Помогите пожалуйста найти мою ошибку ,ни как не могу найти ! Вот задача :

203
Реализация CRC-8. За что отвечает параметр init?

Реализация CRC-8. За что отвечает параметр init?

Кодирую программку для CRC разных стандартов(побитовая обработка) Застрял на параметре init

221
Требуется найти ошибку в коде [требует правки]

Требуется найти ошибку в коде [требует правки]

Программа компилируется, но при запуске и вводе первого значения вылетает ошибкаВ чем проблема понять не могу

190
Использование string в функциях scanf и printf

Использование string в функциях scanf и printf

Могут ли функции scanf и printf работать с переменными типа string? Если да, то как это сделать, например, в данном коде?

269