Java 将4字节转换为整数

Java 将4字节转换为整数,java,data-conversion,Java,Data Conversion,我正在读取一个二进制文件,如下所示: InputStream in = new FileInputStream( file ); byte[] buffer = new byte[1024]; while( ( in.read(buffer ) > -1 ) { int a = // ??? } public static int toInt(byte[] bytes, int offset) { int ret = 0; for (int i=0; i<4 &a

我正在读取一个二进制文件,如下所示:

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

   int a = // ??? 
}
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;
}
a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];
我想做的是读取最多4个字节,并从中创建一个int值,但我不知道怎么做

我觉得我必须一次抓取4个字节,然后执行一个“字节”操作(比如>>>&FF之类的)来创建新的int

这个成语是什么

编辑

哎呀,事实证明这有点复杂(解释一下)

我想做的是,读取一个文件(可能是ascii,二进制,这不重要)并提取它可能包含的整数

例如,假设二进制内容(在基数2中):

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

11111111 11111111 11111111 11111111
将是-1


将是
Integer.MAX\u值(2147483647)
您应该将其放入如下函数中:

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

   int a = // ??? 
}
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;
}
a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];
输出:

11111110111111001111100011110000
这将处理字节不足和正确处理负字节值的问题

我不知道这样做的标准函数

要审议的问题:

  • Endianness:不同的CPU架构将构成int的字节按不同顺序排列。根据你如何想出字节数组开始,你可能不得不担心这一点;及

  • 缓冲:如果您一次抓取1024个字节,并在元素1022处开始一个序列,那么您将在获得4个字节之前到达缓冲区的末尾。最好使用某种形式的缓冲输入流自动进行缓冲,这样您就可以反复使用
    readByte()
    ,而不用担心其他问题

  • 尾随缓冲区:输入的结尾可能是不均匀的字节数(具体来说不是4的倍数),具体取决于源。但是,如果您首先创建输入,并且是4的倍数是“有保证的”(或者至少是一个先决条件),那么您可能不需要担心它

  • 为了进一步阐述缓冲点,考虑:

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

    其次,您还可以使用:

    甚至:

    int i = in.readInt();
    

    而且根本不用担心构造
    int
    s。

    试试这样的方法:

    InputStream in = new FileInputStream( file );
    byte[] buffer = new byte[1024];
    while( ( in.read(buffer ) > -1 ) {
    
       int a = // ??? 
    }
    
    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;
    }
    
    a = buffer[3];
    a = a*256 + buffer[2];
    a = a*256 + buffer[1];
    a = a*256 + buffer[0];
    
    这是假设最低字节排在第一位。如果最高字节排在第一位,您可能需要交换索引(从0到3)

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

    最简单的方法是:

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

    for(int i=0;ia=(aByteBuffer具有此功能,并且能够处理小的和大端的整数

    考虑这个例子:

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

    希望这能有所帮助。

    看看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));
    
    int ch1=in.read();
    int ch2=in.read();
    int ch3=in.read();
    int ch4=in.read();
    如果((ch1 | ch2 | ch3 | ch4)<0)
    抛出新的EOFEException();
    
    return((ch1如果字节[]数组中已经有它们,则可以使用:

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

    来源:

    您也可以对可变长度字节使用biginger。您可以将其转换为Long、Integer或Short,以适合您的需要为准

    new BigInteger(bytes).intValue();
    
    或表示极性:

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

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

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

    long result=((bytes[0]下面的代码从
    数组
    (a
    byte[]
    )的
    索引位置读取4个字节,并返回一个
    int
    。我在Java 10和我想象的一些其他变体上试用了其他答案中的大部分代码

    这段代码使用了最少的CPU时间,但分配了
    ByteBuffer
    ,直到Java10的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;
    
    int结果;
    短数据0、数据1、数据2、数据3;
    data0=(短)(数组[index++]&0x00FF);
    data1=(短)(数组[index++]&0x00FF);
    数据2=(短)(数组[index++]&0x00FF);
    data3=(短)(数组[index++]&0x00FF);
    
    结果=(数据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) );
    
    //逐字节明确声明ANIT=-4
    byte[]anInt={(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xfc};//等于-4
    //现在你有了一个4字节的数组,它的整数等于-4。。。
    //正在从4字节转换回整数。。。
    结果=(int)(anInt[0]16)|((anInt[3]>24));
    
    这里有一个简单的解决方案,对我来说很有效:

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

    <代码> int值=(a和255)+((b和255),我只需考虑我的数组可能不读取确切的<代码> % 4 < /代码>字节。如果数组的长度不是% 4,那么您可以用0填充剩余字节。(由于x | 0:=x和0,因此代码的一个主要问题是java的字节类型是有符号的,因此如果设置了任何字节的最高位,代码也将设置结果int中的所有高位。在移位和oring之前,需要屏蔽每个字节的最高位,例如
    (bytes[0]&0xff)|((bytes[1]&0xff)我不想这么说,但是您的偏移量支持完全被破坏了。请看,我还有修复程序。感谢代码片段,我应该在这里指出一个错误-
    ret |=(int)bytes[I]&0xFF;
    应该是
    ret |=(int)bytes[I+offset]&0xFF;
    -否则偏移量参数将被完全忽略。假设他的二进制文件包含big-endian有符号整数。否则它将失败。非常可怕。:)虽然我在概念上同意Andrey的观点,但我希望任何下降编译器都能解决这个问题并为您解决。然而,@Andrey:公平地说
    int value = (a&255)+((b&255)<<8)+((c&255)<<16)+((d&255)<<24);