【问题标题】:C++: How to read specific number of bytes from a binary file and save it to uint16_t?C++:如何从二进制文件中读取特定数量的字节并将其保存到 uint16_t?
【发布时间】:2019-03-09 21:30:13
【问题描述】:

所以我遇到了这个问题,我对文件的处理不是很熟练,我刚在大学开始 C++ 课,对于第一个作业,基本上我需要从二进制文件中提取特定字节,然后进一步处理它们。

二进制文件如下所示:

01001001 01001001 00000101 00000000 00001010 00000000 00001100 00000000
00101101 00101110 00101111 00110000 00110001 00101000 00101001 00101010
...

其中前 8B 是一些管理属性的 2B 值。 (即 0-2B 是宽度,2-4B 是高度等) 而我需要一一读取这些 2B 属性,并将它们的值保存到 uint16_t 变量中。到目前为止,我得到的最远的是:

int main(void) {
  fstream f1;
  uint16_t endian, width, height, format;

  f1.open("input_01.img", ios::in | ios::binary);

  f1.get((char*) &endian, 2);
  f1.get((char*) &width, 2);
  f1.get((char*) &height, 2);
  f1.get((char*) &format, 2);

  /*...*/
}

这段代码正确读取了第一个 2B,但由于某种原因它停止工作......我不确定我是否不理解 get() 函数的工作原理,或者我的方法是否完全错误......

【问题讨论】:

  • 我不确定你是否可以像这样使用参考转换。
  • @vcloarec 他在拿地址,没有参考。
  • 我不认为你应该使用f1.get() 它停在\n 字符。尝试使用f1.read()
  • @Mirko,当然,我累了……
  • 对不起,我的 b。 '4' 只是一个错字,因为在作业中有不同的文件,这些文件具有不同大小的管理道具......

标签: c++ file input


【解决方案1】:

您需要使用read,而不是get。见http://www.cplusplus.com/reference/istream/istream/read/http://www.cplusplus.com/reference/istream/istream/get/

上面写得很清楚:

2) c-string 从流中提取字符并将它们存储在 s 中 作为 c 字符串,直到 (n-1) 个字符被提取或 遇到分隔符:分隔符 是换行符 ('\n') 或分隔符(如果此参数 已指定)。分隔符不是从 如果找到输入序列,并保留在那里作为下一个字符 从流中提取(参见 getline 的替代方法 丢弃分隔符)。空字符 ('\0') 是 如果 n 大于,则自动附加到写入的序列 零,即使提取了一个空字符串。

所以你会遇到问题,因为换行符和 null 作为二进制数字的一部分是有效字符。还因为就像 tkausl 所说,您正在读取 4 个字节而不是 2 个字节。还因为 get 在之后附加了一个空值。

你可以这样做:

int main(void) {
  fstream f1;
  uint16_t endian, width, height, format;

  f1.open("input_01.img", ios::in | ios::binary);

  f1.read((char*) &endian, sizeof(endian));
  f1.read((char*) &width, sizeof(width));
  f1.read((char*) &height, sizeof(height));
  f1.read((char*) &format, sizeof(format));

  /*...*/
}

如果uint16_t 是正确的,编译器会为您设置大小。

甚至使用模板:

template <class T, class U>
void readFromFile(T& f1, U& variable)
{
    f1.read((char*) &variable, sizeof(variable));
}

然后调用它:

  f1.open("input_01.img", ios::in | ios::binary);

  readFromFile(f1, endian);
  readFromFile(f1, width);
  readFromFile(f1, height);
  readFromFile(f1, format);

当您有几件事情要阅读时,另一种有用的方法是:

// Attribute packed works on GCC, on other compilers you 
// might need a pragma
struct __attribute__((packed)) FileStruct
{
    uint16_t endian= 0;
    uint16_t width= 0;
    uint16_t height= 0;
    uint16_t format= 0;
};
// We check structure size after declaring it; should be 8 bytes long
static_assert(sizeof(FileStruct) == 8, "Size error");

然后:

  FileStruct f;
  f1.open("input_01.img", ios::in | ios::binary);
  readFromFile(f1, f); // f.width has the width, f.format has format, etc.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-22
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 2017-06-04
    • 2021-03-23
    相关资源
    最近更新 更多