Преобразовать 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();