C++ 从二进制文件读取时将大端转换为小端
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3823921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert big endian to little endian when reading from a binary file
提问by starcorn
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.
所以 Big-endian VS Little-endian 只是字节的相反顺序。无论如何,我编写的这个函数似乎可以达到我的目的。我在这里添加了它,以防其他人将来需要它。这仅适用于 double,对于整数,请使用建议的 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;
}
采纳答案by Bryan
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.
假设您要继续,保留一些辅助函数的小库文件会很方便。其中 2 个函数应该是 4 字节值和 2 字节值的字节序交换。对于一些可靠的示例(包括代码),请查看这篇文章。
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.
获得交换函数后,只要读入错误字节序的值,就调用适当的交换函数。有时对于这里的人来说,一个绊脚石是单字节值不需要进行字节序交换,因此如果您正在读取诸如代表文件中字母字符串的字符流之类的内容,那应该很好。只有当您读取一个值为多个字节(如整数值)的值时,您才必须交换它们。
回答by Dingo
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;
回答by QuasarDonkey
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:
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
with similarly-named functions for 16 and 64-bit. So you just say
具有类似名称的 16 位和 64 位函数。所以你只要说
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.
将 little-endian 编码的 32 位整数转换为主机 CPU 编码。这对于读取小端数据很有用。
x = htole32(x);
will convert from the host encoding to 32-bit little-endian. This is useful for writing little-endian data.
将从主机编码转换为 32 位小端。这对于编写小端数据很有用。
Note on BSD systems, the equivalent header file is sys/endian.h
注意在 BSD 系统上,等效的头文件是 sys/endian.h
回答by torak
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.
您可能ntohl
对函数族感兴趣。这些旨在将数据从网络转换为主机字节顺序。网络字节顺序是 big endian,因此在 big endian 系统上它们不做任何事情,而在 little endian 系统上编译的相同代码将执行适当的字节交换。
回答by Mahmoud Fayez
It is good to add that MS has this supported on VS too check this inline functions:
最好补充一点,MS 在 VS 上也支持此功能,请检查此内联函数:
- htond
- htonf
- htonl
- htonll
- htons
- 顿
- 高音
- 通灵
- 通灵
- 吨