反序列化使用 std::wofstream 序列化的对象时,宽字符输入流 std::wifstream 正在损坏

Wide char input stream std::wifstream is getting corrupt while deserializing object which was serialized using std::wofstream

我正在尝试为我的应用程序对象编写自己的自定义序列化和反序列化。我知道有很多库可供使用,例如 boost serialize 等,但我想学习这种序列化和反序列化,因此需要努力。

当我尝试反序列化(使用 std::wifstream)我已经序列化(使用 std::wofstream)的对象时出现问题。甚至无法正确阅读一个 class 成员。我尝试反序列化的前 3 个成员是布尔值,但它们从文件流中读取了不正确的值。有人可以就这里可能出现的问题提出任何建议吗?感谢您的宝贵时间。

应用程序中的类型定义:

namespace fc
{
#ifdef UNICODE
    typedef std::wstring tstring;
    typedef std::wfstream tfstream;
    typedef std::wofstream tofstream;
    typedef std::wifstream tifstream;
    typedef std::wstringstream tstringstream;
#else
    typedef std::string tstring;
    typedef std::fstream tfstream;
    typedef std::ofstream tofstream;
    typedef std::ifstream tifstream;
    typedef std::stringstream tstringstream;
#endif

    typedef std::vector<fc::tstring> tstrvec;
    typedef std::vector<fc::tstring> tstrvec;
}

正在序列化和反序列化的对象:

struct FastCopyCfg
{
    bool mOverwriteFiles;
    bool mCopySystemFiles;
    bool mCopyHiddenFiles;
    fc::tstring mDstFolder;
    fc::tstrvec mSrcFiles;
    fc::tstrvec mSrcFolders;
    fc::tstrvec mIncludeWildcards;
    fc::tstrvec mExcludeWildcards;

    FastCopyCfg()
    {
        mOverwriteFiles = false;
        mCopySystemFiles = false;
        mCopyHiddenFiles = false;
        mDstFolder.clear();
        mSrcFiles.clear();
        mSrcFolders.clear();
        mIncludeWildcards.clear();
        mExcludeWildcards.clear();
    }

    template<typename Archive>
    void Serialize(Archive& ar, const std::uint16_t = 0)
    {
        ar & mCopySystemFiles & mCopyHiddenFiles & mOverwriteFiles &
            mDstFolder & mSrcFiles & mSrcFolders & mIncludeWildcards & mExcludeWildcards;
    }
};

全局插入和提取运算符重载:

void operator >>(IArchive& ar, FastCopyCfg& cfg)
{
    cfg.Serialize(ar);
}

void operator <<(OArchive& ar, FastCopyCfg& cfg)
{
    cfg.Serialize(ar);
}

存档器 classes

class OArchive
{
    std::wostream& mStream;

public:
    OArchive(std::wostream& stream) :mStream(stream){}

    template<typename Val>
    OArchive& operator &(std::vector<Val>& vtr)
    {
        mStream << vtr.size();
        std::for_each(vtr.begin(), vtr.end(), [&](auto e) {mStream << e; });
        return *this;
    }

    template<typename DT>
    OArchive& operator &(DT& data)
    {
        mStream << data;
        return *this;
    }
};

class IArchive
{
    std::wistream& mStream;

public:
    IArchive(std::wistream& stream) :mStream(stream) {}

    template<typename Val>
    IArchive& operator &(std::vector<Val>& vtr)
    {
        std::vector<Val>::value_type vElement;
        std::vector<Val>::size_type vSize = 0;

        mStream >> vSize;
        for (std::vector<Val>::size_type i = 0; i < vSize; i++)
        {
            mStream >> vElement;
            vtr.push_back(vElement);
        }
        return *this;
    }

    template<typename DT>
    IArchive& operator &(DT& data)
    {
        try
        {
            mStream >> data;
        }
        catch (const std::exception& e)
        {
            Logger::logDebug("Exception while reading config file: ", e.what());
        }
        catch (...)
        {
        }
        return *this;
    }
};

使用代码序列化。我将标志设置为 true 和 false 以调试序列化和反序列化。

bool flag = false;
void CFastCopyDlg::OnBnClickedButtonSaveConfiguration()
{
    if (flag)
    {
        fc::tofstream file(fc::CONFIG_FILENAME, fc::tofstream::binary);
        OArchive ar(file);
        ar << getCopyConfig();
    }
    else
    {
        fc::tifstream file(fc::CONFIG_FILENAME, fc::tifstream::binary);
        IArchive ar(file);
        FastCopyCfg cfg;
        ar >> cfg;
    }
}

我想我找到了问题所在。问题是,当文件以二进制模式打开时,使用任何标准 fstream 的反序列化不能使用提取运算符 >> 完成。讨论了类似的话题 HERE。请参考下面的代码,看看问题代码中存在的问题。

class IArchive
{
    std::wistream& mStream;

public:
    IArchive(std::wistream& stream) :mStream(stream) {}

    template<typename Val>
    IArchive& operator &(std::vector<Val>& vtr)
    {
        std::vector<Val>::value_type vElement;
        std::vector<Val>::size_type vSize = 0;

        mStream >> vSize;
        for (std::vector<Val>::size_type i = 0; i < vSize; i++)
        {
            mStream >> vElement;
            vtr.push_back(vElement);
        }
        return *this;
    }

    template<typename DT>
    IArchive& operator &(DT& data)
    {
        try
        {
            mStream >> data; // PROBLEM - BINARY DATA CANNOT BE READ USING >>
        }
        catch (const std::exception& e)
        {
            Logger::logDebug("Exception while reading config file: ", e.what());
        }
        catch (...)
        {
        }
        return *this;
    }
};