如何从c 中的文件中读取小endian整数

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

本文关键字:读取 endian 整数 文件      更新时间:2023-10-16

说我有一个二进制文件;它包含积极的二进制数字,但用 Little Endian编写为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
}

如果您正在使用简短文件,我建议简单地使用类弦乐,然后函数stoul。下面的代码从ifstream读取字节(在本例2字节)中读取字节,并在字符串流中的十六进制中写入它们。然后感谢Stoul将字符串转换为16位整数:

#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;

例如,如果您必须从二进制文件中读取16位整数存储在Big Endian(00 F3)中,则将其放入弦乐(&quot'00f3&quot)中,然后将其转换为整数(243)。该示例在十六进制中写入值,但可以使用类BITSet进行十二月或十月,甚至是二进制。iOmanip函数(setW,setFill)用于为Sstream提供正确的格式。这种方法的不好是,如果您必须处理大小较大的文件,则它的速度非常慢。

您正常读取代码。但是,当您转到解释时,您需要进行适当的转换。

这可能是屁股上的痛苦小到大。在最后两种情况下,没有。

幸运的是,这一切都可以通过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后,测试的十六进制。DAT显示:

01020304 00000010 01000000 04030201