我正在使用boost :: serialize来序列化我使用f.i的文档。一个juce :: String。像这样:
template<class Archive>
void serialize( Archive & ar, const unsigned int version )
{
ar & boost::serialization::make_nvp("title", m_docTitle);
...
}
对于boost :: serialize接受juce :: String作为基本类型我做了:
#include <boost/serialization/string.hpp>
template<class IStream>
inline IStream& operator >> (IStream& stream, juce::String& s)
{
std::wstring t;
stream >> t;
s = juce::String(t.c_str());
return stream;
}
BOOST_CLASS_IMPLEMENTATION(juce::String, boost::serialization::primitive_type)
编译得很好。序列化工作正常,我得到XML中的条目:
<title>DocumentTitle</title>
应该如此。但是,当反序列化时,我可以追踪&gt;&gt;返回的字符串是:
"DocumentTitle</title>"
即。一些XML已被“咀嚼”,后来当然会导致“输入流错误”异常。
最奇怪的部分是,直到一周前我才开始工作...... :(我不知道是什么让它现在不起作用......
编辑:显示重现行为的一个小示例代码,只有依赖是boost:
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/xml_woarchive.hpp>
#include <boost/archive/xml_wiarchive.hpp>
#include <sstream>
class JuceString
{
public:
JuceString(const std::wstring& str = L"") : m_str(str) {;}
JuceString(const JuceString& other) : m_str(other.m_str) {;}
JuceString& operator = (const JuceString& other)
{
if (this != &other)
{
m_str = other.m_str;
}
return *this;
}
const wchar_t* toWideCharPointer() const {
return m_str.c_str();
}
private:
std::wstring m_str;
};
template <class OStream>
OStream& operator<< (OStream& stream, const JuceString& stringToWrite)
{
return stream << stringToWrite.toWideCharPointer();
}
template <class IStream>
IStream& operator>> (IStream& stream, JuceString& s)
{
std::wstring t;
stream >> t;
s = JuceString(t.c_str());
return stream;
}
BOOST_CLASS_IMPLEMENTATION(JuceString, boost::serialization::primitive_type)
class Doc
{
friend class boost::serialization::access;
template<class Archive>
void serialize( Archive & ar, const unsigned int version )
{
ar & boost::serialization::make_nvp("title", m_title);
}
public:
Doc() {;}
Doc(const std::wstring& s) : m_title(s) {;}
private:
JuceString m_title;
};
int main (int argc, char* argv[])
{
std::wstringstream stream;
{
// Serializing document
Doc doc(L"DocumentTitle");
boost::archive::xml_woarchive oa(stream);
oa << boost::serialization::make_nvp("Document", doc);
}
{
// Deserializing document
Doc doc;
try
{
boost::archive::xml_wiarchive ia(stream);
ia >> boost::serialization::make_nvp("Document", doc);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
return 0;
}
使用文本存档可以很好地兼顾......
答案 0 :(得分:2)
最后我通过使用boost basic_xml_grammar解析运算符&gt;&gt;中的字符串,使其工作(对于XML存档而言)。 ,像这样:
typedef boost::archive::basic_xml_grammar<wchar_t> xml_wgrammar;
template <class IStream>
IStream& operator>> (IStream& stream, JuceString& s)
{
std::wstring t;
xml_wgrammar grammar;
if (!grammar.parse_string(stream, t))
{
boost::serialization::throw_exception(
boost::archive::xml_archive_exception(boost::archive::xml_archive_exception::xml_archive_parsing_error)
);
}
s = JuceString(t.c_str());
return stream;
}
这将确保正确解析字符串。
答案 1 :(得分:1)
问题出在您的operator >>
当你这样做时:
std::wstring t;
stream >> t;
你读到下一个空格。在结束标记之后的XML中,因此您正在阅读提升期望能够在那里阅读的流的一部分。
解决方案是强制将额外空间强制输出,或修改operator >>
以拒绝读取任何类似'&lt;'的内容。我的猜测是,之前你在保存和恢复的字符串中有一个额外的空间。
假设您可以从std::wstring
设置/分配并获取某些可用于创建std :: wstring的原始值,这可以在我的机器上运行:
#include <boost/serialization/split_free.hpp>
...
namespace boost {
namespace serialization {
template<class Archive>
void load(Archive & ar, JuceString & j, const unsigned int version)
{
std::wstring tmp;
ar & boost::serialization::make_nvp("value", tmp);
j = tmp;
}
template<class Archive>
void save(Archive & ar, const JuceString & j, const unsigned int version)
{
const std::wstring tmp(j.toWideCharPointer());
ar & boost::serialization::make_nvp("value", tmp);
}
} // namespace serialization
} // namespace boost
BOOST_SERIALIZATION_SPLIT_FREE(JuceString)
这省去了编写operator >>
的需要,并让boost处理直接读取/写入wstring到存档。您只需要编写一次,这样可以避免重复问题,然后您可以随时使用JuceString
。
答案 2 :(得分:0)
我不知道是否有答案,但在比较我的工作区中的代码以序列化ATL CString时,我有以下内容:
inline void serialize(Archive & ar, CString & s, const unsigned int file_version)
{
std::wstring ss( s );
ar & BOOST_SERIALIZATION_NVP(ss);
s = ss.c_str();
}
我想知道你是否可以在operator <<
中做这样的事情 - 不确定这个解决方案是否适用于你。如果没有,请提前道歉。