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

发布于 2024-09-25 14:20:23 字数 1327 浏览 3 评论 0原文

我一直在研究如何将大端转换为小端。但我没有找到任何可以解决我的问题的好方法。似乎有很多方法可以进行这种转换。无论如何,下面的代码在大端系统中工作正常。但是我应该如何编写一个转换函数,以便它也能在小端系统上工作?

这是一项作业,但它只是一个额外的作业,因为学校的系统运行的是大端系统。只是我很好奇,想让它在我的家用电脑上工作也

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

已解决

所以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;
}

I've been looking around how to convert big-endian to little-endians. But I didn't find any good that could solve my problem. It seem to be there's many way you can do this conversion. Anyway this following code works ok in a big-endian system. But how should I write a conversion function so it will work on little-endian system as well?

This is a homework, but it just an extra since the systems at school running big-endian system. It's just that I got curious and wanted to make it work on my home computer also

#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

So Big-endian VS Little-endian is just a reverse order of the bytes. This function i wrote seem to serve my purpose anyway. I added it here in case someone else would need it in future. This is for double only though, for integer either use the function torak suggested or you can modify this code by making it swap 4 bytes only.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

乖乖 2024-10-02 14:20:23

您可以使用一个模板进行字节序交换,该模板将针对数据类型进行概括:

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

You could use a template for your endian swap that will be generalized for the data types:

#include <algorithm>

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

Then your code would end up looking something like:

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;  
青春有你 2024-10-02 14:20:23

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

You might be interested in the ntohl family of functions. These are designed to transform data from network to host byte order. Network byte order is big endian, therefore on big endian systems they don't do anything, while the same code compiled on a little endian system will perform the appropriate byte swaps.

丶视觉 2024-10-02 14:20:23

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编码。这对于读取小端数据很有用。

 x = htole32(x);

将从主机编码转换为 32 位小端编码。这对于写入小端数据很有用。

注意,在 BSD 系统上,等效的头文件是 sys/endian.h

Linux provides endian.h, which has efficient endian swapping routines up to 64-bit. It also automagically accounts for your system's endianness. The 32-bit functions are defined like this:

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

with similarly-named functions for 16 and 64-bit.
So you just say

 x = le32toh(x);

to convert a 32-bit integer in little-endian encoding to the host CPU encoding. This is useful for reading little-endian data.

 x = htole32(x);

will convert from the host encoding to 32-bit little-endian. This is useful for writing little-endian data.

Note on BSD systems, the equivalent header file is sys/endian.h

抱猫软卧 2024-10-02 14:20:23

假设您要继续,保留一个辅助函数的小库文件会很方便。其中 2 个函数应该是 4 字节值和 2 字节值的字节序交换。有关一些可靠的示例(包括代码),请查看这篇文章

获得交换函数后,每当您以错误的字节序读入值时,请调用适当的交换函数。有时,这里的人们的一个绊脚石是单字节值不需要进行字节序交换,因此,如果您正在读取代表文件中字母字符串的字符流之类的内容,那么应该很好。只有当您读取多个字节的值(如整数值)时,您才必须交换它们。

Assuming you're going to be going on, it's handy to keep a little library file of helper functions. 2 of those functions should be endian swaps for 4 byte values, and 2 byte values. For some solid examples (including code) check out this article.

Once you've got your swap functions, any time you read in a value in the wrong endian, call the appropriate swap function. Sometimes a stumbling point for people here is that single byte values do not need to be endian swapped, so if you're reading in something like a character stream that represents a string of letters from a file, that should be good to go. It's only when you're reading in a value this is multiple bytes (like an integer value) that you have to swap them.

長街聽風 2024-10-02 14:20:23

值得补充的是,MS 在 VS 上也支持此功能,请检查此内联函数:

  • htond
  • htonf
  • htonl
  • htonll
  • htons

It is good to add that MS has this supported on VS too check this inline functions:

  • htond
  • htonf
  • htonl
  • htonll
  • htons
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文