首页 文章

从二进制文件读取时将大端转换为小端[重复]

提问于
浏览
15

这个问题在这里已有答案:

我一直在寻找如何将big-endian转换为little-endians . 但我找不到任何可以解决我问题的好处 . 似乎有很多方法可以进行这种转换 . 无论如何,以下代码在big-endian系统中正常工作 . 但是我应该如何编写转换函数,以便它也适用于little-endian系统?

这是一个功课,但它只是一个额外的,因为在学校运行大端系统的系统 . 这只是我很好奇,并希望它也可以在我的家用电脑上工作

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
   ifstream file;

   file.open("file.bin", ios::in | ios::binary);

   if(!file)
      cerr << "Not able to read" << endl;
   else
   {
      cout << "Opened" << endl;

      int i_var;
      double d_var;

      while(!file.eof())
      {
         file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
         file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );
         cout << i_var << " " << d_var << endl;
      }
   }
   return 0;
}

Solved

所以Big-endian VS Little-endian只是字节的逆序 . 我写的这个功能似乎无论如何都符合我的目的 . 我在这里添加它以防万一其他人将来需要它 . 这只是双倍,但是对于整数,要么使用建议的函数torak,要么可以通过使它仅交换4个字节来修改此代码 .

double swap(double d)
{
   double a;
   unsigned char *dst = (unsigned char *)&a;
   unsigned char *src = (unsigned char *)&d;

   dst[0] = src[7];
   dst[1] = src[6];
   dst[2] = src[5];
   dst[3] = src[4];
   dst[4] = src[3];
   dst[5] = src[2];
   dst[6] = src[1];
   dst[7] = src[0];

   return a;
}

5 回答

  • 2

    假设你有一个方便的东西来保存辅助函数的小库文件 . 其中2个函数应该是4字节值的字节序交换和2字节值 . 对于一些可靠的示例(包括代码),请查看this article .

    一旦你有了交换函数,每次读入错误的endian中的值时,都要调用相应的交换函数 . 有时这里的人们的绊脚石是单字节值不需要以字节交换,所以如果你正在读取类似于文件字符串的字符串,那应该是好的 . 只有当你读取一个值时,才需要交换多个字节(如整数值) .

  • 4

    您可以使用模板进行endian交换,该模板将针对数据类型进行推广:

    #include <algorithm>
    
    template <class T>
    void endswap(T *objp)
    {
      unsigned char *memp = reinterpret_cast<unsigned char*>(objp);
      std::reverse(memp, memp + sizeof(T));
    }
    

    然后你的代码最终会看起来像:

    file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
    endswap( &i_var );
    file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );  
    endswap( &d_var );
    cout << i_var << " " << d_var << endl;
    
  • 4

    您可能对ntohl系列函数感兴趣 . 它们旨在将数据从网络转换为主机字节顺序 . 网络字节顺序是大端,因此在大端系统上它们不做任何事情,而在小端系统上编译的相同代码将执行适当的字节交换 .

  • 2

    Linux提供 endian.h ,它具有高达64位的高效字节交换例程 . 它还可以自动计算系统的字节顺序 . 32位函数定义如下:

    uint32_t htobe32(uint32_t host_32bits);           // host to big-endian encoding
    uint32_t htole32(uint32_t host_32bits);           // host to lil-endian encoding
    uint32_t be32toh(uint32_t big_endian_32bits);     // big-endian to host encoding
    uint32_t le32toh(uint32_t little_endian_32bits);  // lil-endian to host encoding
    

    具有类似命名的16位和64位函数 . 所以你要说

    x = le32toh(x);
    

    将little-endian编码的32位整数转换为主机CPU编码 . 这对于读取little-endian数据非常有用 .

    x = htole32(x);
    

    将从主机编码转换为32位little-endian . 这对于编写little-endian数据很有用 .

    关于BSD系统的注意事项,等效的头文件是 sys/endian.h

  • 20

    最好补充说MS在VS上也支持这个内核函数:

    • htond

    • htonf

    • htonl

    • htonll

    • htons

相关问题