【问题标题】:writing struct to .txt file将结构写入 .txt 文件
【发布时间】:2021-10-23 14:48:31
【问题描述】:

我正在尝试使用 boost 将我的结构存储到 txt 文件中,但无法做到。我正在使用 boost 库。 示例结构

struct Frame
{
    uint32_t address{ 0 };
    uint16_t marks{ 0 };
    uint16_t age{ 0 };
    char gender{ 'M' };
    std::string userName;
};

二进制有简单的代码

boost::archive::binary_oarchive ar(ofs, boost::archive::no_header);
ar << boost::serialization::make_binary_object(&f, sizeof(Frame));

假设文件是​​用 fstream object ofs 打开的,'f' 是 'Frame' 的对象

我想知道是否有类似的方式将结构写入txt文件,我不想一一写数据类型。 假设我们不知道结构中数据类型的类型/数量。

【问题讨论】:

  • 由于您的Frame 不是简单可复制的,因此必须通过多次写入流来写入它。如果你不想自己做,你可以使用一个像你现在使用的库。您所说的“相似”是指另一个库还是确切的含义?
  • 我的意思是在同一个 boost 库中,如果有类似的文本存储功能,就像二进制序列化一样。
  • @Ted 在上面的例子中我正在做的是使用 make_binary_object 然后序列化它。我想知道文本是否也有类似的功能。
  • 你读过档案上的documentation 吗?有什么理由不使用text_oarchive?但是请注意,将std::string 写为字节序列是完全没有意义的。
  • @Evg 我是初学者,我正在使用 text_oarchive 但之后我不知道用什么将文本写入文本文件,因为 boost::serialization::make_binary_object 不会t 像二进制一样工作。我想立即编写整个结构,类似于我使用 boost::serialization::make_binary_object 所做的那样,文本也有类似的功能吗?我想知道,因为我找不到它。

标签: c++ boost boost-serialization binary-serialization


【解决方案1】:

正如其他人评论的那样,您必须提供序列化助手,告诉 Boost 如何按成员进行序列化。

如果你只有这样的聚合,你可以用Boost PFR自动生成这个函数到一定程度:

pfr::for_each_field(s, [&](auto&& f) { ar & f; });               

这是一个例子:

namespace MyLib {
    struct Frame {
        uint32_t    address{0};
        uint16_t    marks{0};
        uint16_t    age{0};
        char        gender{'M'};
        std::string userName;
    };

    struct Other {
        std::string userName;
        std::map<uint32_t, std::string> properties;
    };

} // namespace MyLib

请注意,我将它们放在命名空间中以获得良好的风格,而且我们可以强调 ADL 用于查找 serialize 重载。现在让我们定义重载:

namespace MyLib {
    #define SERIALIZER(Aggregate)                                                  \
        template <typename Archive>                                                \
        void serialize(Archive& ar, Aggregate& s, unsigned version)                \
        {                                                                          \
            pfr::for_each_field(s, [&](auto&& f) { ar & f; });               \
        }


    SERIALIZER(Frame)
    SERIALIZER(Other)
} // namespace MyLib

使用宏可以避免重复代码。当然,你也可以不用宏来做到这一点。

现在您可以对两者进行序列化。假设我们有:

MyLib::Frame const diablo{178, 42, 37, 'F', "Diablo"};
MyLib::Other const other{"diablo", {{1, "one"}, {2, "two"}, {3, "three"},}};

然后序列化成文本流:

boost::archive::text_oarchive oa(ss);
oa & diablo;
oa & other;

已经导致包含例如的流

22 serialization::archive 19 0 0 178 42 37 70 6 Diablo 0 0 6 diablo 0 0 3 0 0
 0 1 3 one 2 3 two 3 5 three

完整演示

这个演示检查反序列化的结果实际上与原始结构相同:

Live On Coliru

#include <string>
#include <map>

namespace MyLib {
    struct Frame {
        uint32_t    address{0};
        uint16_t    marks{0};
        uint16_t    age{0};
        char        gender{'M'};
        std::string userName;
    };

    struct Other {
        std::string userName;
        std::map<uint32_t, std::string> properties;
    };

} // namespace MyLib

#include <boost/pfr.hpp>
namespace pfr = boost::pfr;

namespace MyLib {
#define SERIALIZER(Aggregate)                                                  \
    template <typename Archive>                                                \
    void serialize(Archive& ar, Aggregate& s, unsigned version)                \
    {                                                                          \
        pfr::for_each_field(s, [&](auto&& f) { ar & f; });               \
    }

    SERIALIZER(Frame)
    SERIALIZER(Other)
} // namespace MyLib

#include <iostream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/map.hpp>

int main() {
    MyLib::Frame const diablo{178, 42, 37, 'F', "Diablo"};
    MyLib::Other const other{"diablo", {{1, "one"}, {2, "two"}, {3, "three"},}};

    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);
        oa << diablo;
        oa << other;
    }

    std::cout << ss.str() << "\n";

    {
        boost::archive::text_iarchive ia(ss);
        MyLib::Frame f;
        MyLib::Other o;

        ia >> f >> o;

        std::cout << std::boolalpha;
        std::cout << "Frame identical: " << pfr::eq(diablo, f) << "\n";
        std::cout << "Other identical: " << pfr::eq(other, o) << "\n";
    }
}

打印

g++ -std=c++2a -O2 -Wall -pedantic -pthread main.cpp -lboost_serialization && ./a.out
22 serialization::archive 19 0 0 178 42 37 70 6 Diablo 0 0 6 diablo 0 0 3 0 0 0 1 3 one 2 3 two 3 5 three

Frame identical: true
Other identical: true

【讨论】:

猜你喜欢
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2021-02-15
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多