首页 > 解决方案 > 如何在 C++ 中序列化/反序列化 INT

问题描述

所以,我想在 C++ 中为一些 int 变量实现简单的序列化,我真的不知道如何......


我的目标如下:

我本质上希望能够将任何整数转换为二进制,最好使用简单的函数调用。

// Here´s some dummy code of what I essentially want to do

int TestVariable = 25;
String FilePath = "D:\dev\Test.txt";

Serialize(TestVariable, FilePath);

// [...] 
// at some later point in the code, when I want to access the file

Deserialize(&TestVariable, FilePath);


我已经听说过Boost之类的库,但我认为当我只想序列化简单变量时,这有点矫枉过正。



已经提前感谢您的回答。:D

标签: c++visual-studioserializationc++17

解决方案


首先,有一点“不一致”:你要求二进制序列化,看起来像一个文本文件。我会假设你真的想要一个二进制输出。

序列化整数时唯一需要注意的是机器的字节序(即使大多数机器都是小字节序)。

在 C++17 或更低版本中,最简单的方法是运行时检查,例如

inline bool littleEndian()
{
    static const uint32_t test = 0x01020304;
    return *((uint8_t *)&test) == 0x04;
}

C++20 引入了编译时检查,因此您可以将之前的代码重写为

constexpr bool littleEndian()
{
    return std::endian::native == std::endian::little;
}

此时您想要的是以标准方式编写所有整数。通常 BigEndian 是标准。

template <typename T>
inline static T revert(T num)
{
    T res;
    for (std::size_t i = 0; i < sizeof(T); i++)
        ((uint8_t *)&res)[i] = ((uint8_t *)&num)[sizeof(T) - 1 - i];
    return res;
}

此时您的序列化程序将是:

template <typename T>
void serialize(T TestVariable, std::string& FilePath)
{

    static_assert(std::is_integral<T>::value);   //check that T is of {char, int, ...} type
    static_assert(!std::is_reference<T>::value); //check that T is not a reference

    std::ofstream o(FilePath);
    if (littleEndian())
        TestVariable = revert(TestVariable);
    o.write((char *)&TestVariable, sizeof(T));
}

你的反序列化器将是

template <typename T>
void deserialize(T *TestVariable, std::string FilePath)
{
    static_assert(std::is_integral<T>::value);
    std::ifstream i(FilePath);
    i.read((char *)TestVariable, sizeof(T));
    if (littleEndian())
        *TestVariable = revert(*TestVariable);
}

注意:此代码只是一个适用于您的界面的示例,您只需包含<iostream><fstream>如果您使用的是 c++20 版本,请包含<bit>


推荐阅读