【问题标题】:How can I know the size of Cereal's binary output?我怎么知道 Cereal 的二进制输出的大小?
【发布时间】:2017-05-17 20:02:04
【问题描述】:

我正在尝试通过 TCP 链接传输 Cereal 的序列化结果(二进制存档)。对于接收方来说,第一件事是决定恢复消息对象需要(至少)多少字节,但似乎没有办法获取这些信息。

具有所有原始类型成员的结构的序列化结果似乎与结构大小的结果一样大。对此有任何保证吗?我很担心,因为如果由便携式二进制存档序列化,结果会大 1 个字节。我知道这是为了记录字节顺序,但是接收方怎么知道呢?我想出的唯一安全方法是序列化消息并从输出流中获取大小。对于接收方来说,这看起来不太优雅。

【问题讨论】:

    标签: c++ serialization cereal


    【解决方案1】:

    我自己找到了解决方案。在此分享,以防对其他人也有用。

    获取大小最可靠的方法是实际序列化数据,所以我所做的是避免序列化期间通常的内存分配/访问开销(使用 std::stringstream 时)。

    解决方案从 std::basic_streambuf 派生开始(对于 Cereal,它必须是 std::streambuf)

    class COUNTER_BUFFER : public std::streambuf
    {
        private :
            size_t mSize = 0;
    
        private :
            int_type overflow(int_type C)
            {
                return mSize++;
            }
    
        public :
            size_t Size(void) const
            {
                return mSize;
            }
    };
    

    通常从 std::basic_streambuf 派生的类应该将字符写入某个缓冲区(文件、字符串等),但这里它计算写入的字符数(字节)。

    下一步为 std::basic_ostream 分配一个实例,该实例从 Cereal 传递到存档:

    COUNTER_BUFFER Buffer;
    std::basic_ostream<char> Stream(&Buffer);
    cereal::BinaryOutputArchive Archive(Stream);
    

    正常序列化任何数据结构,完成后,调用 Buffer.Size() 获取大小。

    对于只包含原始类型的数据结构,应该有一种方法可以在编译时获取序列化大小,但是使用这种非最佳方法我只能在运行时获取它。

    这对我来说已经足够了。

    【讨论】:

    • overflow的返回值可以溢出,它是一个int。我认为 mSize 应该是 int_type。
    • 认为这应该是安全的。 int_type overflow(int_type C) override { D3UNUSED(C); if (m_size == std::numeric_limits&lt;size_t&gt;::max()) return EOF; // We're gonna overflow so fail. m_size++; return 0; }
    • 更好的解决方案是覆盖xsputn以获得更好的性能。
    • 感谢大家的cmets。我会改进我的解决方案。
    猜你喜欢
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多