繁体   English   中英

如何从 C++ 中的文件中读取小端整数?

[英]How to read little endian integers from file in C++?

假设我有一个二进制文件; 它包含正二进制数,但以小端写成 32 位整数

我如何阅读这个文件? 我现在有这个。

int main() {
    FILE * fp;
    char buffer[4];
    int num = 0;
    fp=fopen("file.txt","rb");
    while ( fread(&buffer, 1, 4,fp) != 0) {

        // I think buffer should be 32 bit integer I read,
        // how can I let num equal to 32 bit little endian integer?
    }
    // Say I just want to get the sum of all these binary little endian integers,
    // is there an another way to make read and get sum faster since it's all 
    // binary, shouldnt it be faster if i just add in binary? not sure..
    return 0;
}

这是一种适用于大端或小端架构的方法:

int main() {
    unsigned char bytes[4];
    int sum = 0;
    FILE *fp=fopen("file.txt","rb");
    while ( fread(bytes, 4, 1,fp) != 0) {
        sum += bytes[0] | (bytes[1]<<8) | (bytes[2]<<16) | (bytes[3]<<24);
    }
    return 0;
}

如果您使用的是Linux,则应在此处查看 ;-)

关于有用的功能,例如le32toh

CodeGuru

inline void endian_swap(unsigned int& x)
{
    x = (x>>24) | 
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}

因此,您可以直接读取到unsigned int ,然后调用它。

while ( fread(&num, 1, 4,fp) != 0) {
    endian_swap(num); 
    // conversion done; then use num
}

如果您正在处理短文件,我建议简单使用 class 字符串流,然后使用 function stoul。 下面的代码从 ifstream 中读取每个字节的字节(在本例中为 2 个字节),并将它们以十六进制形式写入字符串 stream 中。 然后感谢 stoul 将字符串转换为 16 位 integer:

#include <sstream>
#include <iomanip>   

using namespace std;

ifstream is("filename.bin", ios::binary);
if(!is) { /*Error*/ }
is.unsetf(ios_base::skipws); 

stringstream ss;
uint8_t byte1, byte2;
uint16_t val;

is >> byte1; is >> byte2;
ss << setw(2) << setfill('0') << hex << static_cast<size_t>(byte1);
ss << setw(2) << setfill('0') << hex << static_cast<size_t>(byte2);
val = static_cast<uint16_t>(stoul(ss.str(), nullptr, 16));

cout << val << endl;

例如,如果您必须从二进制文件中读取存储在 Big Endian (00 f3) 中的 16 位 integer,则将其放入字符串流 ("00f3") 中,然后将其转换为 integer (243)。 该示例以十六进制写入值,但它可以是十进制或八进制,甚至是二进制,使用 class 位集。 iomanip 函数(setw、setfill)用于为 sstream 提供正确的格式。 这种方法的缺点是,如果您必须处理大文件,它会非常慢。

您可以正常阅读代码。 但是,当您 go解释数据时,您需要进行正确的转换。

这可能会让人头疼,就好像你想让你的代码可移植一样,即在小端和大端机器上运行,你需要处理所有类型的组合:从小到大,从大到小,从小到小和大到大。 在最后两种情况下,无操作。

幸运的是,这一切都可以通过boost::endian 库自动化。 他们文档中的一个例子:

#include <iostream>
#include <cstdio>
#include <boost/endian/arithmetic.hpp>
#include <boost/static_assert.hpp>

using namespace boost::endian;

namespace
{
  //  This is an extract from a very widely used GIS file format.
  //  Why the designer decided to mix big and little endians in
  //  the same file is not known. But this is a real-world format
  //  and users wishing to write low level code manipulating these
  //  files have to deal with the mixed endianness.

  struct header
  {
    big_int32_t     file_code;
    big_int32_t     file_length;
    little_int32_t  version;
    little_int32_t  shape_type;
  };

  const char* filename = "test.dat";
}

int main(int, char* [])
{
  header h;

  BOOST_STATIC_ASSERT(sizeof(h) == 16U);  // reality check

  h.file_code   = 0x01020304;
  h.file_length = sizeof(header);
  h.version     = 1;
  h.shape_type  = 0x01020304;

  //  Low-level I/O such as POSIX read/write or <cstdio>
  //  fread/fwrite is sometimes used for binary file operations
  //  when ultimate efficiency is important. Such I/O is often
  //  performed in some C++ wrapper class, but to drive home the
  //  point that endian integers are often used in fairly
  //  low-level code that does bulk I/O operations, <cstdio>
  //  fopen/fwrite is used for I/O in this example.

  std::FILE* fi = std::fopen(filename, "wb");  // MUST BE BINARY

  if (!fi)
  {
    std::cout << "could not open " << filename << '\n';
    return 1;
  }

  if (std::fwrite(&h, sizeof(header), 1, fi) != 1)
  {
    std::cout << "write failure for " << filename << '\n';
    return 1;
  }

  std::fclose(fi);

  std::cout << "created file " << filename << '\n';

  return 0;
}

编译并执行 endian_example.cpp 后,test.dat 的十六进制转储显示:

01020304 00000010 01000000 04030201

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM