Преобразуйте большой конец в маленький конец, когда читаете из двоичного файла

Я искал, как преобразовать 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