1

我有一个类型的变量uint8_t,我想对其进行序列化并写入文件(这应该是非常便携的,至少对于 Windows 而言,这是我的目标)。

试图以二进制形式将其写入文件,我遇到了这个工作片段:

uint8_t m_num = 3;
unsigned int s = (unsigned int)(m_num & 0xFF);
file.write((wchar_t*)&s, 1); // file = std::wofstream

首先,让我确定我理解这个片段的作用——它需要我的 var(它基本上是一个无符号字符,1 个字节长),将它转换成一个unsigned int(4 个字节长,不那么便携),并使用& 0xFF “提取”仅最低有效字节。

现在,有两件事我不明白:

  1. 为什么首先将其转换为unsigned int,为什么我不能简单地做类似的事情
    file.write((wchar_t*)&m_num, 1);or reinterpret_cast<wchar_t *>(&m_num)?(参考
  2. 我将如何序列化更长的类型,比如 a uint64_t(8 字节长)?unsigned int这里可能不够,也可能不够。
4

2 回答 2

1

uint8_t为 1 个字节,与char

wchar_t在 Windows 中是 2 个字节,在 Linux 中是 4 个字节。它还取决于字节顺序。wchar_t如果可移植性是一个问题,您应该避免。

你可以只使用std::ofstream. Windows 有一个std::ofstream接受 UTF16 文件名的附加版本。这样您的代码与 Windows UTF16 文件名兼容,并且您仍然可以使用std::fstream. 例如

int i = 123;
std::ofstream file(L"filename_in_unicode.bin", std::ios::binary);
file.write((char*)&i, sizeof(i)); //sizeof(int) is 4
file.close();
...
std::ifstream fin(L"filename_in_unicode.bin", std::ios::binary);
fin.read((char*)&i, 4); // output: i = 123

这相对简单,因为它只存储整数。这将适用于不同的 Windows 系统,因为 Windows 始终是 little-endian,并且int大小始终为 4。

但是有些系统是大端的,你必须单独处理。

例如,如果您使用标准 I/O,fout << 123456则整数将存储为文本“123456”。标准 I/O 是兼容的,但它会占用更多磁盘空间并且速度可能会慢一些。

这是兼容性与性能。如果您有大量数据(几兆字节或更多)并且将来可以处理兼容性问题,则继续写入字节。否则使用标准 I/O 会更容易。性能差异通常是不可测量的。

于 2016-06-11T10:08:15.350 回答
0

unit8_t将值写入 a 是不可能的,wofstream因为 awofstream只写入宽字符并且根本不处理二进制值。

如果您要做的是编写一个表示 0 到 255 之间代码点的宽字符,那么您的代码是正确的。

如果您想将二进制数据写入文件,那么您最接近的等价物是ofstream,这将允许您写入字节。

要回答您的问题:

  1. wofstream::write写入宽字符,而不是字节。如果您将地址重新解释m_num为宽字符的地址,您将写入一个 16 位或 32 位(取决于平台)宽字符,其中第一个字节(即最低有效或最高有效,取决于on platform) 是 的值,m_num其余字节是 . 之后内存中发生的任何事情m_num。根据宽字符的字符编码,这甚至可能不是有效字符。即使有效,但在很大程度上是无稽之谈。wofstream::write(如果需要一个宽字符对齐而不是字节对齐的输入,或者m_num紧随其后的是不可读的内存,那么还有其他可能的问题)。

  2. 如果您使用wofstream,那么这是一团糟,我不会解决它。如果您切换到面向字节,ofstream那么您有两个选择。1.如果您只在同一个系统上读取文件,file.write(&myint64value,sizeof(myint64value))就可以了。写入 64 位值的字节的顺序将是未定义的,但是当您回读时将使用相同的顺序,所以这无关紧要。不要尝试做类似的事情,wofstream因为它很危险!2.分别提取 8 个字节中的每一个myint64value(右移 8 位的倍数,然后取低 8 位),然后写入。这是完全可移植的,因为您可以控制写入字节的顺序。

于 2016-06-11T11:36:11.207 回答