Java 将 4 个字节转换为 int
Posted
技术标签:
【中文标题】Java 将 4 个字节转换为 int【英文标题】:Java Convert 4 bytes to int 【发布时间】:2011-02-19 21:02:57 【问题描述】:我想知道这个记录在案的 here 的解决方案是否仍然是解决方案,还是有其他方法从 4 个字节中获取 int?
谢谢。
编辑:我从套接字中获取字节[] .read
编辑:int recvMsgSize = in.read(Data, 0, BufferSize);
如果 recvMsgSize 为 -1,我知道连接已断开。
当我使用 DataInputStream 而不是 InputStream 时如何检测到这一点?
谢谢。
编辑:对于接受正确答案的悠悠球表示歉意。但是在 mihi 更新最终响应之后,该方法似乎是可靠的,并且减少了扩展编码,并且在我看来是最佳实践。
【问题讨论】:
当您从套接字输入流中获取它们时,我会将其包装到 DataInputStream 中并使用它来读取各种数据。特别是因为InputStream.read(byte[])
不能保证读取整个字节数组... DataInputStream.readFully 可以。
[Convert 4 bytes to int ](***.com/questions/2383265/convert-4-bytes-to-int)的可能重复项
【参考方案1】:
取决于你从哪里得到这 4 个字节:
http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()
http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)
您当然仍然可以手动执行,但在大多数情况下使用其中之一(如果您必须转换具有大量字节的字节数组,您可能希望在 ByteArrayInputStream
周围使用 DataInputStream
) 更容易。
编辑:如果需要更改字节序,则必须使用 ByteBuffer,或者自己反转字节,或者自己进行转换,因为 DataInput 不支持更改字节序。
Edit2:当您从套接字输入流中获取它们时,我会将其包装到DataInputStream
中,并使用它来读取各种数据。特别是因为 InputStream.read(byte[]) 不能保证填充整个字节数组...... DataInputStream.readFully 会。
DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);
Edit3:从流中多次读取时,它们将继续从您停止的位置读取,即。 e. aByte 将是字节 0,anInt 将是字节 1 到 4,anInt 将是字节 5 到 8,等等。 readFully 将在所有这些之后继续读取并阻塞,直到它读取 lotOfbytes
。
当流停止(连接断开)时,您将获得 EOFException
而不是 -1,因此如果您获得 -1,则 int 确实是 -1。
如果您根本不想解析任何字节,您可以跳过()它们。使用 DataInputStream 无法以 2 种不同的方式解析一个字节(即首先从字节 0 到 3 读取一个 int,然后从字节 2 到 5 读取一个),但通常也不需要。
例子:
// read messages (length + data) until the stream ends:
while (true)
int messageLength;
try
messageLength = in.readInt(); // bytes 0 to 3
catch (EOFException ex)
// connection dropped, so handle it, for example
return;
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
// all messages handled.
希望这能回答您的其他问题。
【讨论】:
@mihi: in.readFully(lotOfBytes);这会在 int 消息长度标头之后完全读取吗?它是从头开始读取还是在 4 字节 int 数据持有者之后开始读取? java.sun.com/j2se/1.4.2/docs/api/java/io/DataInputStream.html 好的,我现在正在学习 :) @mihi:如何使用 DataInputStream 处理关闭/挂起的连接?即-1?我做一个 readInt 会给出-1吗?请指教。 int recvMsgSize = in.readInt(); (使用 DataInputStream 无法正常工作或检测到连接断开。请告知。 int recvMsgSize = in.read();解决了。谢谢,你的帖子是最有用的。也感谢其他所有人。【参考方案2】:如果您已经将它们放在 byte[]
数组中,则可以使用:
int result = ByteBuffer.wrap(bytes).getInt();
或者,如果您的类路径中有 Google 的 guava-libraries,那么您有快捷方式:
int result = Ints.fromByteArray(array);
它的优点是您可以为其他类型(Longs.fromByteArray
、Shorts.fromByteArray
等)提供同样出色的 API。
【讨论】:
【参考方案3】:功能风格的解决方案(只是为了多样化,恕我直言,使用起来不太方便):
private int addByte (int base, byte appendix)
return (base << 4) + appendix;
public void test()
byte b1 = 5, b2 = 5, byte b3 = 0, b4 = 1;
int result = addByte (addByte (addByte (addByte (0, b1), b2), b3), b4);
【讨论】:
位移不应该是 8,而不是 4?【参考方案4】:您必须非常小心任何扩大转换和数字提升,但下面的代码将 4 byte
转换为 int
:
byte b1 = -1;
byte b2 = -2;
byte b3 = -3;
byte b4 = -4;
int i = ((0xFF & b1) << 24) | ((0xFF & b2) << 16) |
((0xFF & b3) << 8) | (0xFF & b4);
System.out.println(Integer.toHexString(i)); // prints "fffefdfc"
另见
Java code To convert byte to Hexadecimal 注意使用& 0xFF
屏蔽的必要性——如果你使用byte
,你可能最终会做很多这样的事情,因为所有算术运算都会升级为int
(或long
)
【讨论】:
虽然它看起来应该可以工作,但我们确定它不会在有符号位时搞砸吗? 我想你误会了。我想要 4 个字节到 int。不是 int 到 4 个字节。 @ikurtz:已修复。很抱歉造成误解。 @Lo'oris:随时查看最新版本。 正是这个讨论是您应该更好地使用 ByteBuffer 或 DataInput 中预先存在的方法的原因 :-) 它们确实有效。【参考方案5】:正如 mihi 所说,这取决于您从哪里获取这些字节,但这段代码可能有用:
int myNumber = (((int)byteOne) << 0) |
(((int)byteTwo) << 8) |
(((int)byteThree) << 16) |
(((int)byteFour) << 24);
【讨论】:
(int)
是多余且错误的,您需要使用& 0xFF
掩码撤消符号扩展。
这个搞砸了有符号位。多基因润滑剂获胜。以上是关于Java 将 4 个字节转换为 int的主要内容,如果未能解决你的问题,请参考以下文章