Как написать объект в файл на С++

У меня есть объект с несколькими текстовыми строками в качестве членов. Я хочу записать этот объект в файл все сразу, вместо того, чтобы записывать каждую строку в файл. Как я могу это сделать?

Ответ 1

Вы можете переопределить operator>> и operator<< для чтения/записи в поток.

Пример Entry struct с некоторыми значениями:

struct Entry2
{
    string original;
    string currency;

    Entry2() {}
    Entry2(string& in);
    Entry2(string& original, string& currency)
        : original(original), currency(currency)
    {}
};


istream& operator>>(istream& is, Entry2& en);
ostream& operator<<(ostream& os, const Entry2& en);

Реализация:

using namespace std;

istream& operator>>(istream& is, Entry2& en)
{
    is >> en.original;
    is >> en.currency;
    return is;
}

ostream& operator<<(ostream& os, const Entry2& en)
{
    os << en.original << " " << en.currency;
    return os;
}

Затем вы открываете поток, и для каждого вызываемого вами объекта:

ifstream in(filename.c_str());
Entry2 e;
in >> e;
//if you want to use read: 
//in.read(reinterpret_cast<const char*>(&e),sizeof(e));
in.close();

Или вывод:

Entry2 e;
// set values in e
ofstream out(filename.c_str());
out << e;
out.close();

Или если вы хотите использовать потоки read и write, то вы просто замените соответствующий код в реализации operator.

Когда переменные являются частными внутри вашего struct/class, вам нужно объявить operator как методы друзей.

Вы реализуете любой формат/разделители, которые вам нравятся. Когда ваша строка включает пробелы, используйте getline(), которая берет строку и поток вместо >>, потому что operator>> по умолчанию использует пробелы как разделители. Зависит от ваших разделителей.

Ответ 2

Он называется сериализацией. На SO есть много потоков сериализации.

В boost также есть хорошая библиотека сериализации.

http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/index.html

в основном вы можете сделать

myFile<<myObject 

и

myFile>>myObject

с последовательной сериализацией.

Ответ 3

Если у вас есть:

struct A {
    char a[30], b[25], c[15];
    int x;
}

тогда вы можете написать все это только с помощью write (fh, ptr, sizeof (struct a)).

Конечно, это не переносимо (потому что мы не сохраняем конечность или размер "int", но это может быть не проблемой для вас.

Если у вас есть:

struct A {
    char *a, *b, *c;
    int d;
}

то вы не хотите писать объект; вы хотите его сериализовать. Лучше всего посмотреть в Boost библиотеки и использовать их процедуры сериализации, потому что это не простая проблема на языках без отражения.

Ответ 5

Лучший способ - написать каждое поле отдельно вместе с длиной строки.

В качестве альтернативы вы можете создать массив char (или std::vector<char>) и записать все члены в буфер, а затем записать буфер на вывод.

Подлежащий шип заключается в том, что компилятору разрешено вставлять дополнения между членами в классе или структуре. Использование memcpy или std::copy приведет к заполнению байтов, записанных на выходе.

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

Другие люди будут предлагать проверить библиотеку Boost Serialization.

Ответ 6

К сожалению, это, как правило, не совсем возможно. Если ваша структура содержит только простые данные (без указателей или сложных объектов), вы можете сохранить их как один кусок, но при необходимости переносимости необходимо проявлять осторожность. Заполнение, размер типа данных и проблемы с endianess делают эту проблему проблематичной.

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

Ответ 7

Предполагая, что ваша цель как указано, выписать объект одним вызовом write() или fwrite() или что-то еще, сначала нужно скопировать строку и другие данные объекта в один непрерывный блок памяти, Затем вы можете записать() этот блок памяти с помощью одного вызова. Или вы можете сделать векторную запись, вызвав writev(), если этот вызов доступен на вашей платформе.

Тем не менее, вы, вероятно, не выиграете, уменьшив количество вызовов для записи. Особенно, если вы уже используете fwrite() или аналогичную, тогда библиотека C уже выполняет буферизацию для вас, поэтому стоимость нескольких небольших вызовов минимальна. Не подвергайте себя чрезмерной болью и сложностью кода, если это действительно не принесет пользы...