Преобразование Little Endian в Big Endian
Все,
Я занимаюсь проблемами кодирования в Интернете. В настоящее время я работаю над проблемой Problems, где нам нужно преобразовать Big Endian ↔ little endian. Но я не могу записать шаги, рассматривая пример, приведенный как:
123456789 converts to 365779719
Логика, которую я рассматриваю, - это:
1 > Получить целочисленное значение (так как я нахожусь на Windows x86, вход - маленький конец)
2 > Создайте шестнадцатеричное представление того же.
3 > Обратное представление и сгенерируйте целочисленное значение большого конца
Но я, очевидно, что-то пропустил.
Кто-нибудь может направить меня. Я кодирую в Java 1.5
Ответы
Ответ 1
То, что вам нужно понять, это то, что операции с endian заключаются в байтах, представляющих целое число. Таким образом, 4-байтовый номер 27 выглядит как 0x0000001B
. Чтобы преобразовать это число, нужно перейти к 0x1B000000
... В вашем примере шестнадцатеричное представление 123456789 равно 0x075BCD15
, которое должно перейти в 0x15CD5B07
или в десятичной форме 365779719.
Выложенная функция Stacker перемещает эти байты по биту, сдвигая их; более конкретно, оператор i&0xff
принимает младший байт от i
, затем << 24
перемещает его до 24 бит, поэтому с позиций 1-8 до 25-32. Итак, через каждую часть выражения.
Например, код, посмотрите эту утилиту.
Ответ 2
Проверьте это
int little2big(int i) {
return (i&0xff)<<24 | (i&0xff00)<<8 | (i&0xff0000)>>8 | (i>>24)&0xff;
}
Ответ 3
Поскольку большая часть программного обеспечения для написания состоит в повторном использовании существующих решений, первое, что нужно всегда рассматривать в документации для вашего языка/библиотеки.
reverse = Integer.reverseBytes(x);
Я не знаю, насколько эффективна эта функция, но для переключения большого количества чисел ByteBuffer
должна обеспечивать достойную производительность.
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
...
int[] myArray = aFountOfIntegers();
ByteBuffer buffer = ByteBuffer.allocate(myArray.length*Integer.BYTES);
buffer.order(ByteOrder.LITTLE_ENDIAN);
for (int x:myArray) buffer.putInt(x);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.rewind();
int i=0;
for (int x:myArray) myArray[i++] = buffer.getInt(x);
Как указывал eversor в комментариях, ByteBuffer.putInt()
является необязательным методом и может быть недоступен для всех реализаций Java.
Подход DIY
Ответ на укладчик довольно аккуратный, но его можно улучшить.
reversed = (i&0xff)<<24 | (i&0xff00)<<8 | (i&0xff0000)>>8 | (i>>24)&0xff;
Мы можем избавиться от круглых скобок, адаптируя битмаски. E. g., (a & 0xFF)<<8
эквивалентно a<<8 & 0xFF00
. В любом случае, крайние правые скобки не нужны.
reversed = i<<24 & 0xff000000 | i<<8 & 0xff0000 | i>>8 & 0xff00 | i>>24 & 0xff;
Поскольку сдвиг левого сдвига в нулевых битах, первая маска является избыточной. Мы можем избавиться от самой правой маски, используя оператор логического сдвига, который сдвигает только нулевые биты.
reversed = i<<24 | i>>8 & 0xff00 | i<<8 & 0xff0000 | i>>>24;
приоритет оператора, подробные сведения о операторах сдвига находятся в Спецификация языка Java
Ответ 4
Я думаю, что это также может помочь:
int littleToBig(int i)
{
int b0,b1,b2,b3;
b0 = (i&0x000000ff)>>0;
b1 = (i&0x0000ff00)>>8;
b2 = (i&0x00ff0000)>>16;
b3 = (i&0xff000000)>>24;
return ((b0<<24)|(b1<<16)|(b2<<8)|(b3<<0));
}
Ответ 5
следующий метод изменяет порядок бит в байтовом значении:
public static byte reverseBitOrder(byte b) {
int converted = 0x00;
converted ^= (b & 0b1000_0000) >> 7;
converted ^= (b & 0b0100_0000) >> 5;
converted ^= (b & 0b0010_0000) >> 3;
converted ^= (b & 0b0001_0000) >> 1;
converted ^= (b & 0b0000_1000) << 1;
converted ^= (b & 0b0000_0100) << 3;
converted ^= (b & 0b0000_0010) << 5;
converted ^= (b & 0b0000_0001) << 7;
return (byte) (converted & 0xFF);
}