【问题标题】:Boost C++ cross-platform (Windows & Mac) serialization of std::wstring提升 std::wstring 的 C++ 跨平台(Windows 和 Mac)序列化
【发布时间】:2012-01-18 20:41:23
【问题描述】:

我正在为 Windows(使用 Visual Studio 2008)和 Mac(使用 GCC)构建的程序中使用 Boost C++ 库实现序列化。该程序在其大约 30 个类中使用宽字符串 (std::wstring)。根据平台,当我保存到文件时(通过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.cppUTF8-CPPICUDinkumware,但 我还没有看到一个示例可以与我已经使用的解决方案一起使用有(例如,我现在不希望重写五个月的连载工作):

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

myMainClass 包含宽字符串和指向其他类的 Boost 智能指针,这些类反过来会被序列化。

【问题讨论】:

  • 有没有办法为 wstring 添加你自己的加载和保存函数?
  • 什么意思?将序列化拆分为单独的 loadsave 函数?我确实知道该怎么做,但我不确定如果我要编写这些函数,要在 wstrings 上执行什么类型的转换。
  • 我会采用 bames53 的想法,为 wstring 编写一个专门的 boost::serialization 例程。这样,您可以为每个字符选择 2 或 4 个字节,并在两个平台上都使用它。
  • @Tymek 不,我提到的加载和保存功能只是偶然的。我的意思是您可以使用自己的代码覆盖默认的序列化函数,例如,将 wstring 转换为 UTF-8 字符串以进行序列化。例如,如果 wstring 序列化是通过模板实现的,您可以为 wstring 创建自己的模板特化。
  • 您必须决定交换格式(UTF-8、UTF-16、UTF-16BE、UTF16-LE、UTF32...)。

标签: c++ serialization boost wofstream


【解决方案1】:

wofstreamtypedef basic_ofstream&lt;wchar_t, char_traits&lt;wchar_t&gt; &gt; 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 位宽的字符。

【讨论】:

  • 感谢 vine'th。我尝试添加此内容,但遇到编译问题:error: no matching function for call to boost::archive::text_woarchive::text_woarchive(SaveSession()::wofstream_16&amp;) ... candidates are: boost::archive::text_woarchive::text_woarchive(std::wostream&amp;, unsigned int) ... boost::archive::text_woarchive::text_woarchive(const boost::archive::text_woarchive&amp;) 有什么想法吗?
  • 我认为您需要向myMainClass 添加一个重载的wofstream_16&(猜测,如果没有src 很难确定问题。)HTH。
【解决方案2】:

有一个对我有用的简单解决方案。只需理解official documentation 中的这些语句并将它们转换为 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 存储。

【讨论】:

    猜你喜欢
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    相关资源
    最近更新 更多