Запазване и зареждане на данни във файл c++ (за начинаещи)

Имам клас, съдържащ много различни променливи, например има няколко многоизмерни вектора там.

Чувал съм, че можете да съхранявате и зареждате данни директно във файл, но до каква степен?

Например, ако създам екземпляр от този клас, попълня го и след това го запазя във файл, мога ли да го заредя по същия начин? Например как работи това? Трябва ли да запазя всичко наведнъж или трябва да разделя данните по някакъв начин?


person Sebastian Zander    schedule 06.07.2012    source източник
comment
Трябва да конвертирате вашите данни към и от поредица от байтове. Прочетете за сериализацията.   -  person aschepler    schedule 06.07.2012
comment
Търсите сериализация и десериализация. Каква рамка използвате или това е чист STL?   -  person 0xC0000022L    schedule 06.07.2012


Отговори (3)


Това не е точно тема за начинаещи в C++

C++ няма автоматизиран начин за съхраняване/зареждане на вашите обекти във/от файл. Независимо от начина, по който сте избрали, ще трябва да го приложите сами.

Може да изберете да претоварите операторите << и >>, които да използвате с потоци, или може да искате да използвате свои собствени Load и Store методи (или каквито имена сте избрали подходящи, като Serialize / Deserialize). Аз лично предпочитам да създавам собствени функции и да не използвам операторите, но това е само аз.

Ето един прост пример (с претоварени оператори << и >>):

#include <fstream>
#include <iostream>

using namespace std;

class MyClass
{
public:
    MyClass (int x) : m_x(x), m_y(x+1) {}

    friend istream& operator >> (istream& in, MyClass& obj);
    friend ostream& operator << (ostream& out, const MyClass& obj);

private:
    int m_x;
    int m_y;
};

istream& operator >> (istream& in, MyClass& obj)
{
    in >> obj.m_x;
    in >> obj.m_y;
    return in;
}

ostream& operator << (ostream& out, const MyClass& obj)
{
    out << obj.m_x << ' ';
    out << obj.m_y << endl;
    return out;
}

int main(int argc, char* argv[])
{
    MyClass myObj(10);
    MyClass other(1);
    cout << myObj;
    ofstream outFile ("serialized.txt");
    outFile << myObj;
    outFile.close();
    ifstream inFile ("serialized.txt");
    inFile >> other;
    inFile.close();
    cout << other;
    return 0;
}

Струва си да се спомене, че трябва да се погрижите за формата на сериализация. В примера по-горе това е просто текст; но ако ще съхранявате много от тези обекти, може да започнете да мислите за сериализиране на двоични данни (ще трябва да използвате флагове ofstream::binary и ifstream:binary, докато отваряте файловете, и няма да имате нужда от допълнителни разделители, като ' ' и endl във вашия поток за сериализиране).

Обикновено, когато мислите за сериализация, вие също искате да мислите за версиите на вашия поток - и това е друга отделна тема.

person Peter Al    schedule 06.07.2012

Можете да помислите за внедряване на оператори на поток.

С тях можете просто да използвате следното, за да четете и пишете:

fileStream >> yourObject
fileStream << yourObject 

По принцип в оператора >> ще прочетете потока и ще конструирате обекта с намерените данни. В оператора ‹‹ записвате обекта в потока в същия формат, в който очаквате да го прочетете.

Използвайки този начин на работа, можете да сериализирате всеки обект, който имате.

Google за „оператори на поток от претоварване“, за да знаете как да внедрите тези оператори.

person W. Goeman    schedule 06.07.2012
comment
Това правя и аз.. Имам рамка за сериализация, която претоварва едни и същи оператори. Сигурен съм, че някои ще кажат - не изобретявайте колелото и просто използвайте усилване или нещо подобно. Харесва ми да имам контрол над кода, който прави нещо толкова фундаментално. - person Rafael Baptista; 06.07.2012

Можете или да предоставите код, който ще премине през всички членове на даден клас (по избор пропускайки неважните и преобразувайки някои други) и да подготви непрекъснат поток от данни. Това е сериализация в по-тесен смисъл. Често същото нещо трябва да се направи в обратен ред при четене.

В C++ можете също да извършите двоичен дъмп, като CopyMemory(ptr, sizeof(*ptr). Може да работи само ако вашите данни не съдържат указатели (това включва особено скрит указател за класове с виртуални методи). Единствените му предимства са простотата и огромната скорост. Този подход изисква вашите данни да са съседни в паметта, което понякога е полезно само по себе си.

person Agent_L    schedule 06.07.2012