Как записать объект в файл на C ++ - PullRequest
12 голосов
/ 04 марта 2010

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

Ответы [ 7 ]

10 голосов
/ 04 марта 2010

Вы можете переопределить 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.

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

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

6 голосов
/ 04 марта 2010

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

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

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

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

myFile<<myObject 

и

myFile>>myObject

с расширенной сериализацией.

4 голосов
/ 04 марта 2010

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

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 и использовать их подпрограммы сериализации, потому что это непростая проблема для языков без отражения.

1 голос
/ 04 марта 2010

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

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

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

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

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

1 голос
/ 04 марта 2010

На самом деле не все так просто, это C ++, а не PHP или JavaScript.

http://www.parashift.com/c++-faq-lite/serialization.html

В Boost также есть библиотека: http://www.boost.org/doc/libs/release/libs/serialization ... как уже упоминалось в Tronic:)

0 голосов
/ 04 марта 2010

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

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

0 голосов
/ 04 марта 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...