Преобразуйте 4 байта в интервал

Я читаю двоичный файл как это:

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

   int a = // ??? 
}

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

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

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

Править

Ooops это оказывается немного более сложным (для объяснения)

То, что я пытаюсь сделать, читайте, файл (может быть 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 )

69
задан cletus 5 March 2010 в 07:11
поделиться

7 ответов

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

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


//  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's native) format,
//  then set the byte order of the ByteBuffer
if(use_little_endian)
    bb.order(ByteOrder.LITTLE_ENDIAN);

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

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

70
ответ дан 24 November 2019 в 13:44
поделиться

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

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

- или -

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();
5
ответ дан 24 November 2019 в 13:44
поделиться
for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
1
ответ дан 24 November 2019 в 13:44
поделиться

просто посмотрите, как реализован 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));
15
ответ дан 24 November 2019 в 13:44
поделиться

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

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

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

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

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

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

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

  3. 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ов.

27
ответ дан 24 November 2019 в 13:44
поделиться

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

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

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

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

4
ответ дан 24 November 2019 в 13:44
поделиться

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

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

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

32
ответ дан 24 November 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: