Повышение кроссплатформенной сериализации в C ++ (Windows & Mac) std :: wstring - PullRequest
6 голосов
/ 13 декабря 2011

Я реализую сериализацию с использованием библиотек Boost C ++ в программе, созданной для Windows (с использованием Visual Studio 2008) и Mac (с использованием GCC).Программа использует широкие строки (std::wstring) примерно в 30 своих классах.В зависимости от платформы при сохранении в файл (с помощью boost::archive::text_woarchive) широкие строки по-разному отображаются в выходном файле.

Сохраняется в Windows :

H*e*l*l*o* *W*o*r*l*d*!* ...

Сохранено в MacOSX :

H***e***l***l***o*** ***W***o***r***l***d***!*** ...

, где * - символ NULL.

Когда я пытаюсь прочитать файл, созданный в Windows, используяСборка Mac (и наоборот), моя программа аварийно завершает работу.

Насколько я понимаю, Windows до сих пор использует 2 байта на широкий символ, тогда как MacOSX (и я полагаю, Unix в целом) использует 4 байта.

Я сталкивался с возможными решениями, такими как utf8_codecvt_facet.cpp, UTF8-CPP , ICU и Dinkumware , но я еще не виделпример , который будет работать с тем, что у меня уже есть (например, я бы предпочел не переписывать пять месяцев работы по сериализации на этом этапе):

std::wofstream ofs( "myOutputFile" );
boost::archive::text_woarchive oa( ... );
//... what do I put here? ...
oa << myMainClass;

myMainClass содержит широкие строки и Boostумные указатели на другие классы, которые, в свою очередь, сериализуются.

Ответы [ 2 ]

2 голосов
/ 13 декабря 2011

wofstream - это typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;

в Linux, вам нужно объявить пользовательский ofstream для работы с 16-битными символами (в Linux).Это можно сделать следующим образом:

typedef std::uint16_t Char16_t;
typedef basic_ofstream<Char16_t, char_traits<Char16_t> > wofstream_16;

Теперь wofstream_16 можно без проблем использовать на разных платформах для работы с 16-битными символами шириной.

0 голосов
/ 30 июля 2012

Есть простое решение, которое работает для меня. Нужно было просто понять эти утверждения в официальной документации и включить их в синтаксис C ++:

  1. Открыть поток широких символов.
  2. Измените локаль потока для использования boost :: archive :: codecvt_null
  3. Создать архив с флагом no_codecvt.

Так что все вместе выглядит так ( вывод в файл ):

#include <fstream>
#include <locale>

#include <boost/archive/codecvt_null.hpp>
#include <boost/archive/text_woarchive.hpp>
#include <boost/archive/text_wiarchive.hpp>

// (1)
std::wofstream ofs( "myOutputFile.dat" );

// (2)
std::locale loc( ofs.getloc(), new boost::archive::codecvt_null<std::ostream::char_type>() );
ofs.imbue( loc );

// (3) (note text_woarchive)
boost::archive::text_woarchive oa( ofs, boost::archive::no_codecvt );

oa << myMainClass;

Та же идея применима для ввода файла :

std::wifstream ifs( "myInputFile.dat" );

std::locale loc( ifs.getloc(), new boost::archive::codecvt_null<std::ostream::char_type>() );
ifs.imbue( loc );

boost::archive::text_wiarchive ia( ifs, boost::archive::no_codecvt );

ar >> myMainClass;

Выходные файлы на обеих платформах теперь идентичны и хранятся как UTF8.

...