Как прочитать строку из бинарного файла после закрытия программы?

150
29 мая 2019, 03:00

У меня есть структура

struct Order
{
    unsigned int productamount = 0;
    Products product = Products::OOPlabs;
    double cost = 0.0;
    string FIO = "Иванов Иван Иванович";
    unsigned int orderID = 0;
};

Я записываю массив из неё в бинарный файл и читаю при помощи следующих функций:

bool createbinfile(string way, Order* request, int reqlen)
{
    ofstream f(way, ios::trunc | ios::binary);
    if (!f.is_open())
    {
        cout << "Файл не найден\n";
        return false;
    }
    else if (f.rdstate())
    {
        cout << "Ошибка неизвестной природы\n";
        return false;
    }
    f.write((char*)&reqlen, sizeof(int));
    for (int i = 0; i < reqlen; i++)
    {
        f.write(reinterpret_cast<char *>(&request[i].productamount), sizeof(unsigned int));
        f.write(reinterpret_cast<char *>(&request[i].product), sizeof(Products));
        f.write(reinterpret_cast<char *>(&request[i].cost), sizeof(double));
        size_t tmp = request[i].FIO.length();
        f.write(reinterpret_cast<char *>(&tmp), sizeof(size_t));
        f.write(&request[i].FIO[0], tmp);
    }
    f.close();
    return true;
}
bool readbinfile(string way, Order* &request, int &len)
{
    ifstream f(way, ios::binary);
    if (!f.is_open())
    {
        cout << "Файл не найден\n";
        return false;
    }
    else if (f.rdstate())
    {
        cout << "Ошибка неизвестной природы\n";
        return false;
    }
    f.read(reinterpret_cast<char *>(&len), sizeof(int));
    for (int i = 0; i < len; i++)
    {
        f.read(reinterpret_cast<char *>(&request[i].productamount), sizeof(unsigned int));
        f.read(reinterpret_cast<char *>(&request[i].product), sizeof(Products));
        f.read(reinterpret_cast<char *>(&request[i].cost), sizeof(double));
        size_t tmp = 0;
        f.read(reinterpret_cast<char *>(&tmp), sizeof(size_t));
        request[i].FIO.resize(tmp);
        f.read(&request[i].FIO[0], tmp);
    }
    f.close();
    return true;
}

Я могу спокойно записывать и считывать в бинарный файл структуру со строкой во время исполнения программы, но после выхода из неё и повторного чтения - write access violation в void assign () _left was ... (_Right в этот момент равно нуль символу). Я в курсе, что string не POD, но так как мне её записать в бинарном виде? Что именно в этот момент записывается в бинарный файл? Вообще адрес на строку, поэтому я не могу её повторно прочитать, или весь объект строка - поэтому так происходит? Даже если так, как надо записывать в бинарном режиме такой тип данных? Наставьте на путь истинный пожалуйста.

Answer 1

Для полного контроля: при считывании размера списка нужно выделить память под весь массив.

request = (Order*)operator new (sizeof(Order)*len);

Дальше вызвать конструкторы структур на каждый элемент.

for(size_t i=len;i>0;){--i; new (request + i) Order;}

или для краткости:

   request = new Order[len];

Строки там будут уже Иванами. Дальше можно пробовать так , как вы и хотели:

  request[i].FIO.resize(tmp);
  f.read(&request[i].FIO[0], tmp);

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

  for(size_t i=len;i>0;){
      -- i;
      (request + i)->~Order();}
  operator delete (request);    

или для краткости:

delete [] request ;
READ ALSO
VS2010, с++. Подсветка синтаксиса

VS2010, с++. Подсветка синтаксиса

1) Как сделать расширенную цветную подсветку синтаксиса кода в VS2010 для C++? Может, расширение какое-нибудьНапример, как в ReSharper C++ (имена методов...

118
Метод Рунге-Кутта 2 порядка на C++

Метод Рунге-Кутта 2 порядка на C++

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

170
Нужна ли инстанциация класса без вызова функции шаблона?

Нужна ли инстанциация класса без вызова функции шаблона?

Почему эта программа компилируется gcc и msvc (1 и 2), но не компилируется clang (3)? Должна ли она компилироваться в соответствии со стандартом?

88
Возвращаемый тип оператора -&gt;

Возвращаемый тип оператора ->

Почему мне не выдает ошибок при определении, ведь оператор -> должен возвращать указатель или класс, у которого есть -> ?

131