簡體   English   中英

如何序列化/反序列化 C++ 中的 INT

[英]How to serialize / deserialize INTs in C++

所以,我想為 C++ 中的一些 int 變量實現簡單的序列化,我真的不知道如何......


我的目標如下:

我基本上希望能夠將任何 integer 轉換為二進制,最好是通過簡單的 function 調用。

// 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

首先讓我列出不這樣做的原因:

  • 在不同的機器上重用文件是不安全的
  • 速度可能比任何圖書館都慢得多
  • 指針、映射或結構等復雜類型很難正確實現

但是如果你真的要做什么定制,你可以簡單地使用流,這里是一個使用 stringstream 的例子(我總是在我的單元測試中使用 stringstream,因為我希望它們更快),但你可以簡單地修改它以使用 filestream。

請注意,類型必須是默認可構造的,才能被反序列化模板 function 使用。 對於復雜的類,這一定是一個非常嚴格的要求。

#include  <sstream>
#include  <iostream>

template<typename T>
void serialize(std::ostream& os, const T& value)
{
    os << value;
}

template<typename T>
T deserialize(std::istream& is)
{
    T value;
    is >> value;
    return value;
}

int main()
{
    std::stringstream ss;
    serialize(ss, 1353);
    serialize(ss, std::string("foobar"));

    std::cout << deserialize<int>(ss) << " " << deserialize<std::string>(ss) << std::endl;
    return 0;
 }

首先,有一點“不一致”:你要求二進制序列化,看起來像一個文本文件。 我假設你真的想要一個二進制 output。

序列化整數時唯一需要注意的是機器的字節序(即使大多數機器都是小字節序)。

在 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM