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.fromByteArrayShorts.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 注意使用&amp; 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) 是多余且错误的,您需要使用&amp; 0xFF 掩码撤消符号扩展。 这个搞砸了有符号位。多基因润滑剂获胜。

以上是关于Java 将 4 个字节转换为 int的主要内容,如果未能解决你的问题,请参考以下文章

Java bytebuffer 将三个字节转换为 int

Java - 将 Int 转换为字节 - 奇怪的结果

JAVA中int强制转换byte

java中int如何转换byte

如何在飞镖中将 2 个字节转换为 Int16?

求java编程 字节byte怎么转换成整形int?