Boost C ++ cross-platform (Windows and Mac) serialization std :: wstring

I implement serialization using Boost C ++ libraries in a program created for Windows (using Visual Studio 2008) and Mac (using GCC). The program uses wide lines ( std::wstring ) in about 30 classes. Depending on the platform, when I save the file (using boost::archive::text_woarchive ), the wide lines are presented differently in the output file.

Saved on Windows :

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

Saved on MacOSX :

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

where * is the NULL character.

When I try to read a file created under Windows using the Mac build (and vice versa), my program crashes.

In my opinion, Windows initially uses 2 bytes per wide character, while MacOSX (and I assume that Unix in general) uses 4 bytes.

I have utf8_codecvt_facet.cpp across possible solutions such as utf8_codecvt_facet.cpp , UTF8-CPP , ICU and Dinkumware , but I still need to see an example that will work with what I already have (for example, I would prefer not to rewrite five months of serialization work in this moment ):

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

myMainClass contains wide strings and boost smart pointers to other classes, which in turn receive serialization.

+6
source share
2 answers

wofstream typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;

on Linux, you need to declare a custom ofstream to work with 16-bit characters (on linux). This can be done as follows:

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

Now wofstream_16 can be easily used on different platforms for working with 16-bit characters.

+2
source

There is a simple solution to this that works for me. It is just a matter of understanding these statements in the official documentation and turning them into C ++ syntax:

  • Open widescreen stream.
  • Change the flow locale to use boost :: archive :: codecvt_null
  • Create an archive with the no_codecvt flag.

So, together it looks like this ( output to a file ):

 #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; 

The same idea applies to file input:

 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; 

The output files on both platforms are now identical and stored as UTF8.

0
source

Source: https://habr.com/ru/post/903633/


All Articles