【问题标题】:Java Convert 4 bytes to intJava 将 4 个字节转换为 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 ](stackoverflow.com/questions/2383265/convert-4-bytes-to-int)的可能重复项

标签: java casting packing


【解决方案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 数据持有者之后开始读取?
  • @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 掩码撤消符号扩展。
    • 这个搞砸了有符号位。多基因润滑剂获胜。
    猜你喜欢
    • 1970-01-01
    • 2011-09-16
    • 2012-12-15
    • 2020-03-01
    • 2013-01-13
    • 2018-07-04
    • 2012-10-20
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多