Преобразование big endian в little endian при чтении из двоичного файла [дубликат]
этот вопрос уже есть ответ здесь:
Я искал, как преобразовать big-endian в little-endians. Но я не вижу ничего хорошего, что могло бы решить мою проблему. Кажется, есть много способов сделать это. преобразование. В любом случае этот следующий код работает нормально в системе big-endian. Но как написать функцию преобразования, чтобы она работала и в системе little-endian?
это домашнее задание, но это просто дополнительный, так как системы в школе работают с системой big-endian. Просто мне стало любопытно и захотелось, чтобы он работал и на моем домашнем компьютере!--3-->
#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 - это просто обратный порядок байтов. Эта функция, которую я написал, кажется, служит моей цели в любом случае. Я добавил его сюда на случай, если в будущем он понадобится кому-то еще. Это только для double, хотя для integer либо используйте предложенную функцию 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 из этих функций должны быть конечными свопами для 4 байтовых значений и 2 байтовых значений. Для некоторых твердых примеров (включая код) проверьте в этой статье.
Как только у вас есть функции swap, в любое время, когда вы читаете значение в неправильном endian, вызовите соответствующую функцию swap. Иногда камнем преткновения для людей здесь является то, что значения одного байта не должны если Вы читаете что-то вроде символьного потока, который представляет собой строку букв из файла, это должно быть хорошо. Только когда вы читаете в значении это несколько байтов (например, целое значение), вы должны поменять их местами.
вы можете использовать шаблон для вашего endian swap, который будет обобщен для типов данных:
#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;
вас может заинтересовать ntohl
семейство функций. Они предназначены для преобразования данных из сети в порядок байтов хоста. Порядок байтов сети является большим endian, поэтому в больших системах endian они ничего не делают, в то время как тот же код, скомпилированный на маленькой системе endian, будет выполнять соответствующие байтовые свопы.
Linux предоставляет endian.h
, который имеет эффективные процедуры замены endian до 64-бит. Он также автоматически учитывает endianness вашей системы. 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);
преобразовать 32-разрядное целое число в прямой кодировки к узлу кодирования процессора. Это полезно для чтения данных little-endian.
x = htole32(x);
преобразует из кодирование хоста до 32-битного little-endian. Это полезно для записи младший байт данных.
Примечание в системах BSD эквивалентный файл заголовка sys/endian.h
хорошо добавить, что MS поддерживает это на VS тоже проверьте эти встроенные функции:
- htond
- htonf
- htonl
- htonll
- htons