【问题标题】:writing to a binary file in c++在 C++ 中写入二进制文件
【发布时间】:2017-02-18 04:45:03
【问题描述】:

我的问题是我有一个十六进制表示的字符串说: 036e。我想以相同的十六进制表示形式将其写入二进制文件。我首先使用sstrtoul() 函数将字符串转换为整数。然后 我使用fwrite() 函数将其写入文件。这是我写的代码。运行此程序后,我在文件中得到以下输出:

6e03 0000

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
  ofstream fileofs("binary.bin", ios::binary | ios::out);
  string s = "036e";
  int x = strtoul(s.c_str(), NULL, 16);
  fileofs.write((char*)&x, sizeof(int));
  fileofs.close();
}

虽然我期望的结果是这样的:

036e

谁能解释一下我在这里做错了什么?

【问题讨论】:

  • 调整您的期望,使其与现实相符。显然你正在一个小端平台上工作,其中sizeof(int) 是 4。期望 2 字节违反逻辑,就像期望大端布局一样。
  • 我尝试改用unsigned short。但它会输出一些垃圾结果。

标签: c++ file binary hex filestream


【解决方案1】:

您的问题与endianees 以及整数的大小有关。

对于反转字节的解释是你在一个小端系统中运行。

对于额外的 2 个零,解释是您使用的是 32 位编译器,其中 int 有 4 个字节。

只要您始终在 32 位小端系统中使用它,您的代码就没有问题。

如果您保留系统,如果您使用类似代码从文件中读取整数,您将获得正确的值(您的第一个读取整数将是 0x36E)。

要按照您的意愿编写数据,您可以使用完全相同的代码,只需稍作改动,如下所述:

unsigned short x = htons(strtoul(s.c_str(), NULL, 16));
fileofs.write((char*)&x, sizeof(x));

但是您必须注意,当您读回数据时,您必须使用ntohs() 将其转换为正确的格式。如果您以这种方式编写代码,它将在任何编译器和系统中工作,因为网络顺序总是相同的,并且转换函数只会在必要时执行数据更改。

您可以在on another thread herein the linux.com man page for those functions找到更多信息。

【讨论】:

  • 谢谢。知道了。但我仍然想知道是否有任何方法可以将字符串“03e6”作为十六进制写入二进制文件(可能不将其转换为 int)?
  • 如果您只有 2 个字节,您可以使用 short 而不是 int,并在转换后的数据之上使用 htons() 函数。我会用完整的例子来改变我的答案。
【解决方案2】:

如果您想要 16 位,请使用保证为 16 位的数据类型。 uint16_t from cstdint 应该可以解决问题。

下一个字节序。

这是described in detail 很多地方。 TL;DR 版本是一些系统,几乎每台您可能为其编写代码的台式 PC 都将它们的整数与字节 BACKWARD 一起存储。无法解释原因,但当您深入了解常见的使用模式时,它确实是有道理的。

所以你看到的 036e 是两个字节,03 和 6e,并且首先存储在最低有效字节 6e 中。这样计算机看到的是一个包含 6e03 的两字节值。这是写入输出文件的内容,除非您采取措施强制对输出进行排序。

有很多不同的方法来强制排序,但让我们专注于一种始终有效(即使移植到已经是大端序的系统)并且易于阅读的方法。

uint16_t in;
uint8_t out[2];

out[0] = (in >> 8) & 0xFF; // put highest in byte in first out byte
out[1] = in & 0xFF; // put lowest in byte in second out byte

out 然后写入文件。

Recommended supplementary reading: Serialization 这将有助于解释常见的下一个问题:“为什么我的字符串在我读回它们后会导致程序崩溃?”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多