Сериализация classа, который содержит std :: string

Я не эксперт на C ++, но в прошлом я делал сериализацию несколько раз. К сожалению, на этот раз я пытаюсь сериализовать class, который содержит std :: string, который, как я понимаю, в значительной степени похож на сериализацию указателя.

Я могу записать class в файл и снова прочитать его. Все int-поля прекрасны, но поле std :: string дает ошибку «адрес за пределами границ», по-видимому, потому, что указывает на данные, которых больше нет.

Существует ли стандартное обходное решение для этого? Я не хочу возвращаться к массивам символов, но, по крайней мере, я знаю, что они работают в этой ситуации. Я могу предоставить код, если это необходимо, но я надеюсь, что я хорошо объяснил свою проблему.

Я сериализую, выставив class в char * и записывая его в файл с файлом fstream. Чтение, конечно, только наоборот.

Я сериализую, выставив class в char * и записывая его в файл с файлом fstream. Чтение, конечно, только наоборот.

К сожалению, это работает только до тех пор, пока нет указателей. Возможно, вы захотите присвоить своим classам void MyClass::serialize(std::ostream) и void MyClass::deserialize(std::ifstream) и вызвать их. В этом случае вы хотите

 std::ostream& MyClass::serialize(std::ostream &out) const { out << height; out << ',' //number seperator out << width; out << ',' //number seperator out << name.size(); //serialize size of string out << ',' //number seperator out << name; //serialize characters of string return out; } std::istream& MyClass::deserialize(std::istream &in) { if (in) { int len=0; char comma; in >> height; in >> comma; //read in the seperator in >> width; in >> comma; //read in the seperator in >> len; //deserialize size of string in >> comma; //read in the seperator if (in && len) { std::vector tmp(len); in.read(tmp.data() , len); //deserialize characters of string name.assign(tmp.data(), len); } } return in; } 

Вы также можете перегрузить streamовые операторы для более удобного использования.

 std::ostream &operator<<(std::ostream& out, const MyClass &obj) {obj.serialize(out); return out;} std::istream &operator>>(std::istream& in, MyClass &obj) {obj.deserialize(in); return in;} 

Просто запись двоичного содержимого объекта в файл не только не переносима, но, как вы признали, не работает для данных указателя. В основном у вас есть два варианта: либо вы пишете настоящую библиотеку сериализации, которая правильно обрабатывает std :: strings, например, используя c_str () для вывода фактической строки в файл, или вы используете отличную библиотеку сериализации boost . Если это вообще возможно, я бы рекомендовал последнее, вы можете сериализовать с помощью простого кода, подобного этому:

 #include  #include  #include  class A { private: std::string s; public: template void serialize(Archive& ar, const unsigned int version) { ar & s; } }; 

Здесь serialize функции работает для сериализации и десериализации данных в зависимости от того, как вы это называете. Дополнительную информацию см. В документации.

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

При чтении вы сначала читаете размер, затем выделяете строку, а затем заполняете ее, читая правильное количество байтов из streamа.

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

Вам придется использовать более сложный метод сериализации, чем приведение classа в char* и запись его в файл, если ваш class содержит любые экзогенные данные ( string ). И вы правильно знаете, почему вы получаете ошибку сегментации.

Я бы сделал функцию-член, которая бы взяла fstream и прочитала бы в нем данные, а также обратную функцию, которая возьмет fstream и запишет ее содержимое для ее восстановления позже, например:

 class MyClass { pubic: MyClass() : str() { } void serialize(ostream& out) { out << str; } void restore(istream& in) { in >> str; } string& data() const { return str; } private: string str; }; MyClass c; c.serialize(output); // later c.restore(input); 

Вы также можете определить operator<< и operator>> для работы с ostream и ostream для сериализации и восстановления вашего classа, если вы хотите использовать этот синтаксический сахар.

Почему не просто что-то вроде:

 std::ofstream ofs; ... ofs << my_str; 

а потом:

 std::ifstream ifs; ... ifs >> my_str; 
 /*! * reads binary data into the string. * @status : OK. */ class UReadBinaryString { static std::string read(std::istream &is, uint32_t size) { std::string returnStr; if(size > 0) { CWrapPtr buff(new char[size]); // custom smart pointer is.read(reinterpret_cast(buff.m_obj), size); returnStr.assign(buff.m_obj, size); } return returnStr; } }; class objHeader { public: std::string m_ID; // serialize std::ostream &operator << (std::ostream &os) { uint32_t size = (m_ID.length()); os.write(reinterpret_cast(&size), sizeof(uint32_t)); os.write(m_ID.c_str(), size); return os; } // de-serialize std::istream &operator >> (std::istream &is) { uint32_t size; is.read(reinterpret_cast(&size), sizeof(uint32_t)); m_ID = UReadBinaryString::read(is, size); return is; } }; 

Я не кодировал C ++ в течение длительного времени, но, возможно, вы могли бы сериализовать массив char .

Затем, когда вы открываете файл, ваша string будет просто указывать на массив.

Просто идея.

  • Ошибка JSON.NET Локальный цикл привязки для типа
  • Невозможно десериализовать lambda
  • Удаление десериализации JSON в объект с помощью Json.NET
  • Сериализация нулевого значения в JSON.NET
  • Сериализация JSON массива с полиморфными объектами
  • Специальная сериализация Jackson JSON для определенных полей
  • ТипNameHandling предостережение в Newtonsoft Json
  • XSLT: как преобразовать XML-узел в строку
  • Сериализовать статический class?
  • Сериализация jacksonа JSON, предотrotation рекурсии путем определения уровня
  • Как настроить сериализацию списка объектов JAXB для JSON?
  • Давайте будем гением компьютера.