Преобразовать 4 байта в int

Я читаю двоичный файл следующим образом:

InputStream in = new FileInputStream( file );
byte[] buffer = new byte[1024];
while( ( in.read(buffer ) > -1 ) {

   int a = // ??? 
}

Что я хочу сделать, чтобы прочитать до 4 байтов и создать значение int из них, но я не знаю, как это сделать.

Мне кажется, что я должен брать по 4 байта за один раз и выполнять одну операцию "байт" (например, → < < → и FF и тому подобное), чтобы создать новый int

Какая идиома для этого?

ИЗМЕНИТЬ

В этом случае это будет немного сложнее (объяснить)

То, что я пытаюсь сделать, это прочитать файл (может быть, ascii, двоичный, это неважно) и извлечь целые числа, которые он может иметь.

Например, предположим, что двоичный контент (в базе 2):

00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010

Целочисленное представление должно быть 1, 2 вправо?: -/1 для первых 32 бит и 2 для остальных 32 бит.

11111111 11111111 11111111 11111111

Будет -1

и

01111111 11111111 11111111 11111111

Будет Integer.MAX_VALUE ( 2147483647 )

Ответ 1

ByteBuffer имеет эту возможность и способен работать как с маленькими, так и с большими целыми числами endian.

Рассмотрим следующий пример:


//  read the file into a byte array
File file = new File("file.bin");
FileInputStream fis = new FileInputStream(file);
byte [] arr = new byte[(int)file.length()];
fis.read(arr);

//  create a byte buffer and wrap the array
ByteBuffer bb = ByteBuffer.wrap(arr);

//  if the file uses little endian as apposed to network
//  (big endian, Java native) format,
//  then set the byte order of the ByteBuffer
if(use_little_endian)
    bb.order(ByteOrder.LITTLE_ENDIAN);

//  read your integers using ByteBuffer getInt().
//  four bytes converted into an integer!
System.out.println(bb.getInt());

Надеюсь, что это поможет.

Ответ 2

Вы должны поместить его в такую ​​функцию:

public static int toInt(byte[] bytes, int offset) {
  int ret = 0;
  for (int i=0; i<4 && i+offset<bytes.length; i++) {
    ret <<= 8;
    ret |= (int)bytes[i] & 0xFF;
  }
  return ret;
}

Пример:

byte[] bytes = new byte[]{-2, -4, -8, -16};
System.out.println(Integer.toBinaryString(toInt(bytes, 0)));

Вывод:

11111110111111001111100011110000

Это позаботится об истечении байтов и правильной обработке отрицательных байтов.

Я не знаю стандартной функции для этого.

Вопросы для рассмотрения:

  • Endianness: различные архитектуры процессора помещают байты, которые составляют int в разных порядках. В зависимости от того, как вы начинаете использовать массив байтов, вам, возможно, придется беспокоиться об этом; и

  • Буферизация:, если вы захватите 1024 байта за раз и запустите последовательность в элементе 1022, вы попадете в конец буфера, прежде чем вы получите 4 байта. Вероятно, лучше использовать некоторую форму буферизованного входного потока, который автоматически выполняет буферизацию, поэтому вы можете просто использовать readByte() несколько раз и не беспокоиться об этом в противном случае;

  • Trailing Buffer: конец ввода может быть нечетным количеством байтов (не кратным 4) в зависимости от источника. Но если вы создаете вход для начала и будучи кратным 4, это "гарантировано" (или, по крайней мере, предварительное условие), вам может и не понадобиться беспокоиться о нем.

для дальнейшего уточнения точки буферизации, рассмотрите BufferedInputStream:

InputStream in = new BufferedInputStream(new FileInputStream(file), 1024);

Теперь у вас есть InputStream, который автоматически буферизирует 1024 байта за раз, что намного менее неудобно. Таким образом, вы можете с радостью читать 4 байта за раз и не беспокоиться о слишком большом количестве операций ввода-вывода.

Во-вторых, вы также можете использовать DataInputStream:

InputStream in = new DataInputStream(new BufferedInputStream(
                     new FileInputStream(file), 1024));
byte b = in.readByte();

или даже:

int i = in.readInt();

и не беспокоиться о создании int вообще.

Ответ 3

Если вы уже в массиве byte [], вы можете использовать:

int result = ByteBuffer.wrap(bytes).getInt();

источник: здесь

Ответ 4

просто посмотрите, как реализована DataInputStream.readInt();

    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));

Ответ 5

Самый простой способ:

RandomAccessFile in = new RandomAccessFile("filename", "r"); 
int i = in.readInt();

- или -

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();

Ответ 6

попробуйте что-то вроде этого:

a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];

это предполагает, что младший байт приходит первым. если старший байт на первом месте, вам, возможно, придется поменять индексы (перейдите от 0 до 3).

в основном для каждого байта, который вы хотите добавить, сначала умножьте на 256 (что равно сдвигу влево на 8 бит), а затем добавьте новый байт.

Ответ 7

for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}

Ответ 8

Вы также можете использовать BigInteger для байтов переменной длины. Вы можете преобразовать его в Long, Integer или Short, в зависимости от ваших потребностей.

new BigInteger(bytes).intValue();

или обозначить полярность:

new BigInteger(1, bytes).intValue();