Сохранить vector в файл и считать оттуда

329
28 августа 2017, 08:26

Имеется структура:

struct str
{
int a;
bool b;
};

Также есть вторая:

struct str2
{
int c;
int d[5];
std::vector<str>vec;
};

На её основе строится вектор:

std::vector<str2>vec_2;

Нужно сохранить этот вектор в файл, а также считать из файла обратно в память.

Answer 1

То, что вы хотите, называется сериализациея/десериализация. Существует довольно много решений на этот счет, например, boost::serialization.

Одним из простых кросплатформенных способов сериализации является использование QDataStream и перегрузка operator << и operator >> для пользовательских типов. Любой массив записывается в виде

stream << std::int64_t{array.size};
for(auto&& x: array)
  stream << x;

и считывается в обратном порядке, для контейнеров из Qt уже предусмотрены перегрузки.

Пример перегрузок:

QDataStream& operator << (QDataStream& stream, const str& rha){
  return stream 
    << int64_t{rha.a}
    << rha.b;
}
QDataStream& operator >> (QDataStream& stream, const str& rha){
  int64_t a; // Нужен платформонезависимый тип
  stream >> a;
  rha.a = a;
  stream >> rha.b;
  return  stream;
}
str str_1 {123, false};
str str_2;
{
  File file("file.dat");
  file.open(QIODevice::WriteOnly);
  QDataStream out(&file);
  out << str1; 
}
{
  File file("file.dat");
  file.open(QIODevice::ReadOnly);
  QDataStream in(&file);
  in >> str2; 
}

Для обработки ошибок можно бросать исключения (без этого есть шанс заполнить все структуры нулями и долго искать ошибку).

Строки таким образом сериализовывать нельзя, нужно преобразовывать их в нормальный массив, например, в utf8, и уже его записывать, т.к. чтение и запись строк в потоки обычно не симметричны.

То же самое можно делать и со стандартными потоками, но там есть проблема с кросплатформенностью.

Answer 2

Для начала нужно определить методы чтения/записи вашей структуры. Для этой цели хорошо подходят операторы << и >>.

std::ostream& operator<<(std::ostream &os, const str &value){
    os << value.a << value.b;
    return os; 
}
std::istream& operator>>(std::istream &is, str &value){
    is >> value.a >> value.b;
    return is; 
}

Теперь писать структуру в файл можно так:

std::fstream ofs("file");
str s;
ofs << s;

а читать так:

std::fstream ifs("file");
str s;
ifs >> s;

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

std::fstream ofs("file");
std::vector<str> v = {...};
std::copy(v.begin(), v.end(), std::ostream_iterator<str>(ofs));

Чтобы прочитать вектор структур, можно сделать так:

std::fstream ifs("file");
std::vector<str> v;
std::copy(std::istream_iterator<str>(ifs), std::istream_iterator<str>(), std::back_inserter(v));

Это была инструкция для str. Вам нужно выполнить аналогичные действия и для str2.

READ ALSO
Отслеживание состояние процесса

Отслеживание состояние процесса

Добрый вечер - интересует такой вопросВозможно ли создать такую программу, которая будит проводить мониторинг другого процесса на пример...

276
Потокобезопасная обертка над объектом

Потокобезопасная обертка над объектом

Есть ли минусы, которые могут заставить не использовать подобные оберткиТакже подскажите, есть ли уже что-то подобное в stl или boost

314
Uncaught TypeError: $.ajax is not a function

Uncaught TypeError: $.ajax is not a function

Uncaught TypeError: $ajax is not a function at HTMLParagraphElement

428