【问题标题】:read unsigned long from binary file从二进制文件中读取 unsigned long
【发布时间】:2017-05-18 04:31:54
【问题描述】:

我正在尝试从二进制文件中读取 unsigned long 数字。
我是这样做的:

    infile.open("file.bin", std::ios::in | std::ios::binary);
    char* U=new char[sizeof(unsigned long)];
    unsigned long out=0;
    infile.read(U, sizeof(unsigned long));
    out=static_cast<unsigned long>(*U);
    delete[] U;
    U=NULL;
    infile.close();

但结果不正确。
我的数据是6A F2 6B 58 00 00 00 00,女巫应该读作1483469418,但在我的代码中是106,这只是数据的第一个字节

有什么问题?
我应该如何从文件中正确读取unsigned long

【问题讨论】:

  • 您期望什么字节序格式以及您使用什么格式?在处理多字节整数值时要注意这一点。
  • 您只是将第一个字节转换为无符号长整数。此外,由于 endanness,该方法无论如何都不可移植。
  • @tadman:文件和系统都是 LE
  • @A.S.H:我怎样才能正确且无字节序地做到这一点?

标签: c++ binaryfiles readfile


【解决方案1】:

那是因为你正在转换一个取消引用的值。 IE。只有一个 char 不是完整的 4 个字节。 *U106

你可以在没有中间缓冲区的情况下读取数据:

infile.read(reinterpret_cast&lt;char*&gt;(&amp;out), sizeof out);

不同之处在于这里你重新解释了指针,而不是它下面的值。

如果你还想使用缓冲区,它应该是*reinterpret_cast&lt;unsigned long*&gt;(U);,这也会重新解释指针 1st,然后取消引用它。关键是取消引用正确类型的指针。指针的类型决定了该值使用了多少字节。

【讨论】:

  • 使用新的/错误类型的缓冲区有什么原因吗?为什么不直接将它传递给它已经期望的值呢? Endianess 至少让我害怕......
  • 恐怕我没有完全理解你。使用缓冲区没有错,我没有说。在 OP 的情况下这是多余的,所以我实际上给出了一个将值直接存储到变量中的示例。但是如果想使用缓冲区,我给出了第二个选项。如果需要,可以在强制转换之前交换字节,但 OP 似乎并不关心字节序。
  • 啊废话 - 我的错.. 没有看到 out 的定义是什么 - 然后继续 :)
【解决方案2】:

out=static_cast(U);应该是out=(unsigned long *)(U);

它可以简单得多:

infile.open("file.bin", std::ios::in | std::ios::binary);
unsigned long out=0;
infile.read((char *)&out, sizeof(out));
infile.close();

【讨论】:

    【解决方案3】:

    试试out=*reinterpret_cast&lt;unsigned long *&gt;(U);

    【讨论】:

      【解决方案4】:

      您需要知道文件(而不是程序)是大端还是小端。然后用 fgetc() 读取字节并重新构造数字

      所以

        unsigned long read32be(FILE *fp)
        {
            unsigned long ch0, ch1, ch2 ch3;
      
            ch0 = fgetc(fp);
            ch1 = fgetc(fp);
            ch2 = fgetc(fp);
            ch3 = fgetc(fp);
      
            return (unsigned long) (ch0 << 24) | (ch1 << 16) | (ch2 << 8) | ch3
        }
      

      现在无论 longs 是 32 位还是 64 位、big_endian 还是 little endian,它都可以工作。如果 file 是 little endian,则交换 fgetc()s 的顺序。

      以便携方式读取二进制文件非常棘手。我已经在github上放了一些代码

      https://github.com/MalcolmMcLean/ieee754

      【讨论】:

      • 我会争辩说这是 c,而不是 c++,而且它根本没有帮助。您是否建议 OP 将所有 IO 例程交换为 c?无论字节顺序如何,它都不起作用。您需要手动更改读取顺序。你可以对 OPs 代码做同样的事情。只需在 U 内容上使用 swap
      • 无论机器的字节序如何,它都能正常工作。无论文件的字节序如何,都无法正确解析文件。
      • 无论机器字节序如何,原始代码也可以工作。把这两件事分开是虚幻的。重要的是机器/系统与文件字节序。如果两者相同,则没有问题。如果它们不同,则需要交换字节。所以是的,无论文件是字节序,都可以正确读取文件。您需要在具有相同字节序的机器上阅读它。我的观点是,不可能做出一个普遍的案例,并且建议某些东西不管字节顺序如何都可以工作,而没有任何类型的条件字节交换是烟雾和屏幕。你只是转移了问题。
      • 请不要误会我的意思。你提出了一个重要问题。不过,这是c 中答案的一半,根本没有解决和解释 OP 遇到的问题。这是一个完全正交的东西。所以我不是特别喜欢它。
      猜你喜欢
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 2018-08-24
      • 2015-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多