76

我正在读取这样的二进制文件:

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

整数表示应该是12对吧?:- / 前 32 位为 1,其余 32 位为 2。

11111111 11111111 11111111 11111111

将是-1

01111111 11111111 11111111 11111111

将会 Integer.MAX_VALUE ( 2147483647 )

4

12 回答 12

75

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());

希望这可以帮助。

于 2010-03-05T00:25:33.303 回答
37

如果您已经将它们放在 byte[] 数组中,则可以使用:

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

来源:这里

于 2010-05-15T14:08:46.007 回答
30

你应该把它放到这样的函数中:

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. 字节序:不同的 CPU 架构将组成 int 的字节以不同的顺序排列。根据您如何提出字节数组开始,您可能不得不担心这一点;和

  2. 缓冲:如果您一次抓取 1024 个字节并在元素 1022 处开始一个序列,您将在获得 4 个字节之前到达缓冲区的末尾。使用某种形式的缓冲输入流可能会更好,它会自动进行缓冲,这样您就可以readByte()重复使用而不必担心它;

  3. 尾随缓冲区:输入的结尾可能是奇数个字节(具体不是 4 的倍数),具体取决于源。但是,如果您首先创建输入并且“保证”是 4 的倍数(或至少是一个先决条件),您可能不需要关心它。

要进一步详细说明缓冲点,请考虑BufferedInputStream

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

现在你有一个一次InputStream自动缓冲1024 个字节的缓冲区,处理起来不那么尴尬了。这样您就可以愉快地一次读取 4 个字节,而不必担心太多的 I/O。

其次,您还可以使用DataInputStream

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

甚至:

int i = in.readInt();

根本不用担心构建ints 。

于 2010-03-04T22:45:06.817 回答
18

看看 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));
于 2010-03-05T10:52:54.847 回答
5

最简单的方法是:

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

- 或者 -

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();
于 2010-03-04T22:48:25.873 回答
4

尝试这样的事情:

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

这是假设最低字节首先出现。如果最高字节首先出现,您可能必须交换索引(从 0 到 3)。

基本上对于要添加的每个字节,首先将a乘以256(等于向左移动 8 位),然后添加新字节。

于 2010-03-04T22:46:37.610 回答
3

这是一个对我有用的简单解决方案:

int value = (a&255)+((b&255)<<8)+((c&255)<<16)+((d&255)<<24);

a 是最低有效字节

b 是第二个最低有效字节

c 是第二个最重要的字节

d 是最高有效字节

于 2021-05-29T21:51:30.177 回答
1
for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
于 2010-03-04T22:49:53.080 回答
1

您还可以将 BigInteger 用于可变长度字节。您可以根据需要将其转换为 Long、Integer 或 Short。

new BigInteger(bytes).intValue();

或表示极性:

new BigInteger(1, bytes).intValue();
于 2013-07-31T20:36:40.383 回答
1

为了将无符号 4 字节读取为整数,我们应该使用 long 变量,因为符号位被视为无符号数的一部分。

long result = (((bytes[0] << 8 & bytes[1]) << 8 & bytes[2]) << 8) & bytes[3]; 
result = result & 0xFFFFFFFF;

这是测试良好的功能

于 2018-04-07T05:52:21.427 回答
0

将 4 字节数组转换为整数:

//Explictly declaring anInt=-4, byte-by-byte
byte[] anInt = {(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xfc}; // Equals -4
//And now you have a 4-byte array with an integer equaling -4...
//Converting back to integer from 4-bytes...
result = (int) ( anInt[0]<<24 | ( (anInt[1]<<24)>>>8 ) | ( (anInt[2]<<24)>>>16) | ( (anInt[3]<<24)>>>24) );
于 2019-03-17T13:41:46.860 回答
0

以下代码从array(a byte[]) 的位置读取 4 个字节index并返回 a int。我尝试了 Java 10 上其他答案的大部分代码以及我梦想的其他一些变体。

此代码使用的 CPU 时间最少,但会分配 aByteBuffer直到 Java 10 的 JIT 摆脱分配。

int result;

result = ByteBuffer.
   wrap(array).
   getInt(index);

此代码是不分配任何内容的最佳性能代码。不幸的是,与上述代码相比,它消耗的 CPU 时间多 56%。

int result;
short data0, data1, data2, data3;

data0  = (short) (array[index++] & 0x00FF);
data1  = (short) (array[index++] & 0x00FF);
data2  = (short) (array[index++] & 0x00FF);
data3  = (short) (array[index++] & 0x00FF);
result = (data0 << 24) | (data1 << 16) | (data2 << 8) | data3;
于 2018-11-23T18:39:18.917 回答