将 4 个字节转换为 int

发布于 08-24 02:30 字数 857 浏览 5 评论 0原文

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

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 对吗? :- / 1 表示前 32 位,2 表示其余 32 位。

11111111 11111111 11111111 11111111

将为 -1

01111111 11111111 11111111 11111111

Integer.MAX_VALUE ( 2147483647 )

I'm reading a binary file like this:

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

   int a = // ??? 
}

What I want to do it to read up to 4 bytes and create a int value from those but, I don't know how to do it.

I kind of feel like I have to grab 4 bytes at a time, and perform one "byte" operation ( like >> << >> & FF and stuff like that ) to create the new int

What's the idiom for this?

EDIT

Ooops this turn out to be a bit more complex ( to explain )

What I'm trying to do is, read a file ( may be ascii, binary, it doesn't matter ) and extract the integers it may have.

For instance suppose the binary content ( in base 2 ) :

00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010

The integer representation should be 1 , 2 right? :- / 1 for the first 32 bits, and 2 for the remaining 32 bits.

11111111 11111111 11111111 11111111

Would be -1

and

01111111 11111111 11111111 11111111

Would be Integer.MAX_VALUE ( 2147483647 )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

美煞众生2024-08-31 02:30:45

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

希望这有帮助。

ByteBuffer has this capability, and is able to work with both little and big endian integers.

Consider this example:


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

Hope this helps.

素手挽清风2024-08-31 02:30:45

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

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

source: 此处< /a>

If you have them already in a byte[] array, you can use:

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

source: here

浅唱々樱花落2024-08-31 02:30:45

您应该将其放入这样的函数中:

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

根本不用担心构造 int

You should put it into a function like this:

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;
}

Example:

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

Output:

11111110111111001111100011110000

This takes care of running out of bytes and correctly handling negative byte values.

I'm unaware of a standard function for doing this.

Issues to consider:

  1. Endianness: different CPU architectures put the bytes that make up an int in different orders. Depending on how you come up with the byte array to begin with you may have to worry about this; and

  2. Buffering: if you grab 1024 bytes at a time and start a sequence at element 1022 you will hit the end of the buffer before you get 4 bytes. It's probably better to use some form of buffered input stream that does the buffered automatically so you can just use readByte() repeatedly and not worry about it otherwise;

  3. Trailing Buffer: the end of the input may be an uneven number of bytes (not a multiple of 4 specifically) depending on the source. But if you create the input to begin with and being a multiple of 4 is "guaranteed" (or at least a precondition) you may not need to concern yourself with it.

to further elaborate on the point of buffering, consider the BufferedInputStream:

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

Now you have an InputStream that automatically buffers 1024 bytes at a time, which is a lot less awkward to deal with. This way you can happily read 4 bytes at a time and not worry about too much I/O.

Secondly you can also use DataInputStream:

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

or even:

int i = in.readInt();

and not worry about constructing ints at all.

许你一世情深2024-08-31 02:30:45

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

just see how DataInputStream.readInt() is implemented;

    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));
狼性发作2024-08-31 02:30:45

最简单的方法是:

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

-- 或 --

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

The easiest way is:

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

-- or --

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();
乜一2024-08-31 02:30:45

尝试这样的事情:

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

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

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

try something like this:

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

this is assuming that the lowest byte comes first. if the highest byte comes first you might have to swap the indices (go from 0 to 3).

basically for each byte you want to add, you first multiply a by 256 (which equals a shift to the left by 8 bits) and then add the new byte.

世界等同你2024-08-31 02:30:45

这是一个适合我的简单解决方案:

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

a 是最低有效字节

b 是第二最低有效字节

c 是第二最高有效字节

d 是最高有效字节

Here is a simple solution that works for me:

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

a is the least significant byte

b is the second least significant byte

c is the second most significant byte

and d is the most significant byte

丶情人眼里出诗心の2024-08-31 02:30:45
for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
魔法少女2024-08-31 02:30:45

您还可以使用 BigInteger 来表示可变长度字节。您可以将其转换为长整型、整数或短整型,具体取决于您的需要。

new BigInteger(bytes).intValue();

或表示极性:

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

You can also use BigInteger for variable length bytes. You can convert it to Long, Integer or Short, whichever suits your needs.

new BigInteger(bytes).intValue();

or to denote polarity:

new BigInteger(1, bytes).intValue();
匿名的好友2024-08-31 02:30:45

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

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

这是经过测试运行良好的功能

For reading unsigned 4 bytes as integer we should use a long variable, because the sign bit is considered as part of the unsigned number.

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

This is tested well worked function

乖乖兔^ω^2024-08-31 02:30:45

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

这段代码使用了最少的 CPU 时间,但分配了一个 ByteBuffer,直到 Java 10 的 JIT 摆脱了分配。

int result;

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

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

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;

The following code reads 4 bytes from array (a byte[]) at position index and returns a int. I tried out most of the code from the other answers on Java 10 and some other variants I dreamed up.

This code used the least amount of CPU time but allocates a ByteBuffer until Java 10's JIT gets rid of the allocation.

int result;

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

This code is the best performing code that does not allocate anything. Unfortunately, it consumes 56% more CPU time compared to the above code.

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;
飘落散花2024-08-31 02:30:45

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

Converting a 4-byte array into integer:

//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) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文