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