谷歌序列化CString Vector

时间:2018-06-02 00:47:45

标签: c++ visual-c++ vector mfc cereal

编辑://由于下面的答案,它已经正常工作,添加了当前正在运行的代码和测试用例,以防万一有人觉得它很有用。

// Add as another type for Cereal or inside string.hpp in Cereal includes      
  template<class Archive> inline
      void CEREAL_SAVE_FUNCTION_NAME(Archive & ar, CString str)
  {
      // Save number of chars + the data
      size_type size = (str.GetLength() + 1) * sizeof(TCHAR);
      ar(size);
      ar(binary_data(str.GetBuffer(), static_cast<std::size_t>(size)));
      str.ReleaseBuffer();
  }

  template<class Archive> inline
      void CEREAL_LOAD_FUNCTION_NAME(Archive & ar, CString & str)
  {
      size_type size;
      ar(size);
      ar(binary_data(str.GetBuffer(static_cast<std::size_t>(size)), static_cast<std::size_t>(size)));
      str.ReleaseBuffer();
  }

下面是我用来测试的代码,它正确输出了向量的所有元素。

class Stuff
{
public:
    Stuff() {}
    std::vector<CString> vec;
private:
    friend class cereal::access;
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(vec);
    }
};

int main()
{
    Stuff myStuff, otherStuff;

    myStuff.vec.push_back(L"Testing different length CStrings");
    myStuff.vec.push_back(L"Separator");
    myStuff.vec.push_back(L"Is it working yet??");
    myStuff.vec.push_back(L"1234567890");
    myStuff.vec.push_back(L"TestingTestingTestingtestingTesting");

    {
    std::ofstream file("out.txt", std::ios::binary);
    cereal::BinaryOutputArchive output(file);
    output(myStuff);
    }

    {
        std::ifstream file("out.txt", std::ios::binary);
        cereal::BinaryInputArchive input(file);
        input(otherStuff);
    }

    int nSize = otherStuff.vec.size();

    for (int x = 0; x < nSize; x++)
    {
        std::wcout << (LPCWSTR)otherStuff.vec[x] << std::endl;
    }
    return 0;
}

感谢Barmak Shemirani的帮助。

1 个答案:

答案 0 :(得分:1)

如果你的序列化类知道如何处理std::vector<std::string>(你应该用不同大小的字符串测试它),它也可能知道如何处理CString(宽字符版本),将其视为二进制数据,假设文件以二进制打开。

这些标志需要在Windows中以二进制模式打开:

std::ofstream file("out.txt", std::ios::binary);
std::ifstream file("out.txt", std::ios::binary);

如果序列化类使用文本文件进行存储,则不要使用二进制模式,请阅读下一行:

或者,您可以将CString(UTF16)转换为UTF8

std::vector<std::string> vec;
vec.push_back((const char*)CW2A(L"abc-unicode-ελληνική", CP_UTF8));

从存档中读取后,您必须转换回CString

CString s = CA2W(vec[0].c_str(), CP_UTF8);

<小时/> 在二进制文件中,使用正确的大小来保存CString。类似的东西:

CEREAL_SAVE_FUNCTION_NAME...
size_type size = (str.GetLength() + 1) * sizeof(TCHAR);
ar(size);
ar(binary_data(str.GetBuffer(), size));
str.ReleaseBuffer();

在阅读CString时,请通过调用str.GetBuffer(size)而不是str.GetBuffer()来确保缓冲区足够大。代码应如下所示:

CEREAL_LOAD_FUNCTION_NAME...
size_type size;
ar(size);
ar(binary_data(str.GetBuffer(size), size);
str.ReleaseBuffer();

要序列化矢量,保存矢量的维度,然后保存每个矢量元素。要读取矢量维,然后从存档中读取那么多元素。除非您的序列化类具有自动化功能。