我正在读这样的二进制文件:
InputStream in = new FileInputStream( file );
byte[] buffer = new byte[1024];
while( ( in.read(buffer ) > -1 ) {
int a = // ???
}
我想做什么来读取最多4个字节并从那些创建一个int值但是,我不知道该怎么做。
我觉得我必须一次抓取4个字节,并执行一个“字节”操作(如>><<>>& FF和类似的东西)来创建new int
这是什么成语?
修改
哎呀这个结果有点复杂(解释)
我要做的是,读取一个文件(可能是ascii,二进制,无所谓)并提取它可能具有的整数。
例如假设二进制内容(在基数2中):
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
整数表示应为1
,2
对吗? : - 前1位为32位,其余32位为2位。
11111111 11111111 11111111 11111111
将是-1
和
01111111 11111111 11111111 11111111
将是Integer.MAX_VALUE ( 2147483647 )
答案 0 :(得分:69)
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());
希望这有帮助。
答案 1 :(得分:27)
你应该把它放到这样的函数中:
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:不同的CPU架构将构成int的字节放在不同的顺序中。根据您开始使用字节数组的方式,您可能不得不担心这一点;以及
缓冲:如果你一次抓取1024个字节并在元素1022处开始一个序列,你将在获得4个字节之前到达缓冲区的末尾。最好使用某种形式的缓冲输入流自动缓冲,这样你就可以反复使用readByte()
而不用担心;
尾随缓冲区:输入的结尾可能是不均匀的字节数(具体为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
。
答案 2 :(得分:27)
答案 3 :(得分:14)
看看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));
答案 4 :(得分:5)
最简单的方法是:
RandomAccessFile in = new RandomAccessFile("filename", "r");
int i = in.readInt();
- 或 -
DataInputStream in = new DataInputStream(new BufferedInputStream(
new FileInputStream("filename")));
int i = in.readInt();
答案 5 :(得分:4)
尝试这样的事情:
a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];
这假设最低字节首先出现。如果最高字节首先出现,则可能需要交换索引(从0到3)。
基本上对于要添加的每个字节,首先将 a 乘以256(等于向左移位8位),然后添加新字节。
答案 6 :(得分:1)
for (int i = 0; i < buffer.length; i++)
{
a = (a << 8) | buffer[i];
if (i % 3 == 0)
{
//a is ready
a = 0;
}
}
答案 7 :(得分:1)
您还可以将BigInteger用于可变长度字节。您可以将其转换为Long,Integer或Short,以满足您的需求。
new BigInteger(bytes).intValue();
或表示极性:
new BigInteger(1, bytes).intValue();
答案 8 :(得分:1)
这是一个对我有用的简单解决方案:
int value = (a&255)+((b&255)<<8)+((c&255)<<16)+((d&255)<<24);
a 是最低有效字节
b 是第二个最低有效字节
c 是第二个最重要的字节
d 是最高有效字节
答案 9 :(得分:0)
为了读取无符号的4个字节作为整数,我们应该使用一个长变量,因为符号位被认为是无符号数的一部分。
long result = (((bytes[0] << 8 & bytes[1]) << 8 & bytes[2]) << 8) & bytes[3];
result = result & 0xFFFFFFFF;
这是经过测试的良好功能
答案 10 :(得分:0)
以下代码从位置array
的{{1}}(byte[]
)读取4个字节,并返回index
。我从Java 10上的其他答案以及我梦dream以求的一些其他变体中试用了大部分代码。
这段代码使用了最少的CPU时间,但是分配了int
,直到Java 10的JIT取消了分配。
ByteBuffer
此代码是性能最好的代码,不分配任何内容。不幸的是,与上面的代码相比,它消耗了56%的CPU时间。
int result;
result = ByteBuffer.
wrap(array).
getInt(index);
答案 11 :(得分: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) );