Подтвердить что ты не робот

Как преобразовать 4-байтовый массив в целое число?

Я хочу выполнить преобразование, не прибегая к трюку, зависящему от реализации. Какие-нибудь советы?

4b9b3361

Ответ 1

Вам нужно знать достоверность ваших байтов.

Предполагая (например, @WhiteFang34), что bytes является byte[] длины 4, тогда...

тупоконечника:

int x = java.nio.ByteBuffer.wrap(bytes).getInt();

Little-младшему:

int x = java.nio.ByteBuffer.wrap(bytes).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();

Ответ 2

Предполагая, что bytes представляет собой byte[4] целого числа в порядке возрастания, обычно используемого в сети:

int value = ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16)
        | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);

& 0xFF необходимы, потому что byte подписан на Java, и вам нужно сохранить бит-бит здесь. Вы можете изменить процесс следующим образом:

bytes[0] = (byte) ((value >> 24) & 0xFF);
bytes[1] = (byte) ((value >> 16) & 0xFF);
bytes[2] = (byte) ((value >> 8) & 0xFF);
bytes[3] = (byte) (value & 0xFF);

Ответ 3

Вам нужно указать порядок байтов массива, но если предположить, что bytes[0] является самым значительным байтом, то:

int res = ((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) |
          ((bytes[2] & 0xff) << 8)  | (bytes[3] & 0xff);

Этот код переносится на 100%, предполагая, что вы используете обратный алгоритм для создания массива байтов в первую очередь.


Проблемы с порядком байтов возникают в языках, где вы можете отличать собственный тип целочисленного типа и тип массива байтов... и затем обнаруживать, что разные архитектуры хранят байты целого числа в разных порядках.

Вы не можете сделать это на Java. Поэтому для связи с Java-Java это не должно быть проблемой.

Однако, если вы отправляете или получаете пакеты в какое-либо удаленное приложение, которое реализовано в (скажем) C или С++, вам нужно "знать", какой порядок байтов используется в сетевых пакетах. Некоторые альтернативные стратегии для понимания/определения этого:

  • Каждый использует "сетевой порядок" (big-endian) для вещей на проводе в соответствии с приведенным выше примером кода. Не-Java-приложения на машинах с маленькими концами необходимо перевернуть байты.

  • Отправитель выясняет, какой заказчик ожидает и использует этот заказ при сборке данных.

  • Получатель определяет, какой порядок используется отправителем (например, через флаг в пакете) и декодирует соответственно.

Первый подход является самым простым и наиболее широко используемым, хотя он приводит к 2 ненужным преобразованиям endian-ness, если оба отправителя и получателя малозначительны.

См. http://en.wikipedia.org/wiki/Endianness

Ответ 4

Не уверен, что это правильный синтаксис java, но как насчет:

int value = 0;
for (i = 0; i <= 3; i++)
    value = (value << 8) + (bytes[i] & 0xFF);

Ответ 5

Предполагая, что ваш байт [] пришел откуда-то, например. поток, который вы можете использовать

DataInputStream dis = ... // can wrap a new ByteArrayInputStream(bytes)
int num = dis.readInt(); // assume big-endian.

или

ByteChannel bc = ... // can be a SocketChannel
ByteBuffer bb = ByteBuffer.allocate(64*1024);

bc.read(bb);
bb.flip();
if (bb.remaining()<4) // not enough data

int num = bb.getInt();

Когда вы отправляете данные, вы должны знать, отправляете ли вы большой или маленький конец. Вы должны взять на себя другие вещи, например, отправляете ли вы 4-байтовое целое число со знаком. Бинарный протокол полон предположений. (Что делает его более компактным и быстрым, но более хрупким, чем текст)

Если вы не хотите делать столько допущений, отправьте текст.

Ответ 6

Мы также можем использовать следующее, чтобы сделать его более динамическим размером массива байтов
Формат BigEndian:

public static int pareAsBigEndianByteArray(byte[] bytes) {
    int factor = bytes.length - 1;
    int result = 0;
    for (int i = 0; i < bytes.length; i++) {
        if (i == 0) {
            result |= bytes[i] << (8 * factor--);
        } else {
            result |= bytes[i] << (8 * factor--);
        }
    }
    return result;
}

Маленький формат Endian:

public static int pareAsLittleEndianByteArray(byte[] bytes) {
    int result = 0;
    for (int i = 0; i < bytes.length; i++) {
        if (i == 0) {
            result |= bytes[i] << (8 * i);
        } else {
            result |= bytes[i] << (8 * i);
        }
    }
    return result;
}

Это поможет вам много для преобразования байтов в значения int

Ответ 7

public static int toInt( byte[] bytes ) {
int result = 0;
for (int i=0; i<3; i++) {
  result = ( result << 8 ) - Byte.MIN_VALUE + (int) bytes[i];
}
return result;
}