用XML宽存档来增强juce :: String的反序列化问题

问题描述

|| 我正在使用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>
应该是。但是,在反序列化时,我可以在>>运算符中跟踪返回的字符串为:
\"DocumentTitle</title>\"
也就是说,某些XML已被“修改”,这当然会在以后导致“输入流错误”异常。 最奇怪的部分是我直到一周前才完成这项工作... :(我不知道是什么使它现在无法正常工作... 编辑:一个显示示例的小示例代码再现了该行为,只有依赖关系得到了增强:
#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;
}
而是使用文本存档在两种情况下都可以正常工作...     

解决方法

最终,通过使用boost basic_xml_grammar解析operator >>中的字符串,我使它可以工作(对于XML存档nota bene),如下所示:
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;
}
这将确保正确解析该字符串。     ,问题出在你的ѭ6 当您这样做时:
std::wstring t;
stream >> t;
您读到下一个空格。在XML中,它位于结束标记之后,因此您正在读取boost希望能够在其中读取的部分流。 解决方案是要么在输出中强加一个空格,要么修改
operator >>
以拒绝读取\'<\'之类的内容。我的猜测是,以前您要保存和恢复的字符串中有多余的空间。 假设您可以从
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读/写到存档中。您也只需编写一次,这样就避免了重复问题,然后您可以随意使用often13ѭ。     ,我不知道是否有答案,但是在比较工作区中的代码以序列化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();
}
我想知道您是否可以在ѭ15中做类似的事情-不确定此解决方案是否适用于您。如果没有的话,请提前道歉。