【问题标题】:Representing a number in a byte array (java programming)在字节数组中表示一个数字(java编程)
【发布时间】:2011-02-21 13:42:01
【问题描述】:

我试图在一个两字节数组中表示端口号 9876(或十六进制的 0x2694):

class foo {
     public static void main (String args[]) {
   byte[] sendData = new byte[1];

   sendData[0] = 0x26;
   sendData[1] = 0x94;
     }
}

但是我收到了一个关于可能会丢失精度的警告:

foo.java:5: possible loss of precision
found   : int
required: byte
   sendData[1] = 0x94;
                 ^
1 error

如何在两字节数组中表示数字 9876 而不会丢失精度?

注意:我选择了@Björn 的代码作为正确答案,但@glowcoder 的代码也很好用。这只是解决同一问题的不同方法。谢谢大家!

【问题讨论】:

  • 请注意,通过网络发送的扁平化数据结构通常使用 Java 中的 DataOutputStream(或其子类 ObjectOutputStream)来完成。无需每次都重新发明bitfiddling :-)
  • @meriton: 更好的是,使用java.nio.ByteBuffer 可以做到这一切,不必处理 IOException,也可以控制字节序。

标签: java arrays bytearray hex


【解决方案1】:

您是否尝试过转换为字节?例如

sendData[1] = (byte)0x94;

【讨论】:

  • 那会导致我的精度下降,不是吗?
  • @Mark:它会让编译器清楚你正在做你想做的事。 0x94 在一个字节的范围内,所以这里没有实际的精度损失。
  • 我以为一个字节的范围是-128到127,0x94是148
  • @Mark - 0x94 作为一个字节实际上不是 148,而是 -108。
  • @Mark:嗯……不。看位,一个字节的范围是0b00000000到0b11111111,0x94=0b10010100,正好在它的范围内。按位,“有符号字节”的概念没有任何意义。只有当您将八位序列解释为整数时,它才开始变得清晰。
【解决方案2】:

0x94 是十进制的 148,超出了 java 中字节的范围(-128 到 127)。 您可以执行以下操作之一:

1) 强制转换可以正常工作,因为它将保留二进制表示(对于 0x00 到 0xFF,没有有意义的位被截断):

 sendData[1] = (byte)0x94; 

2) 0x94 作为有符号字节的二进制表示是-108(-0x6C),所以下面的效果是一样的:

sendData[1] = -0x6C; //or -108 in decimal

【讨论】:

  • 要将有符号字节转换回其无符号整数形式,您可以简单地写b & 0xff
【解决方案3】:

Björn 对使用流给出了一个很好的通用答案。你也可以使用java.nio.ByteBuffer 来做同样的事情,这会导致代码稍微少一些,并且你还可以控制输出的字节序(字节顺序)。

创建字节数组:

public static byte[] toByteArray(int bits) {
    ByteBuffer buf = ByteBuffer.allocate(4);
    buf.putInt(bits);
    return buf.array();
}

反转它:

public static int fromByteArray(byte[] b) {
    ByteBuffer buf = ByteBuffer.wrap(b);
    return buf.getInt();
}

【讨论】:

    【解决方案4】:

    我的第一个答案是位移,但再想一想,我认为使用输出流可能会更好,更容易理解。我通常避免强制转换,但如果您不寻求通用解决方案,我想这没关系。 :)

    使用流,一个通用的解决方案:

    public byte[] intToByteArray(final int i) throws java.io.IOException {
        java.io.ByteArrayOutputStream b = new java.io.ByteArrayOutputStream();
        java.io.DataOutputStream d = new java.io.DataOutputStream(b);
        d.writeInt(i);
        d.flush();
    
        return b.toByteArray();
    }
    

    然后反转它:

    public int byteArrayToInt(final byte[] b) throws IOException {
        java.io.ByteArrayInputStream ba = new java.io.ByteArrayInputStream(b);
        java.io.DataInputStream d = new java.io.DataInputStream(ba);
    
        return d.readInt();
    }
    

    【讨论】:

    • 您也可以使用 java.nio.ByteBuffer 进行一般性操作,并在必要时控制字节序。我已经为这种可能性添加了答案。
    【解决方案5】:

    您必须转换为 (byte),因为 java 中的默认数字类型是 int,它大于 byte。只要值适合字节,就可以转换。

    【讨论】:

      【解决方案6】:

      试试这个:

      sendData[0] =(byte)0x26
      sendData[1] =(byte)0x94
      

      或者这个:

      sendData[0] =(byte)38
      sendData[1] =(byte)148
      

      您必须将数据转换为字节才能将其分配给字节!

      这并不意味着你失去了精度,只是写 0x26 意味着一个 int 到 Java 编译器..

      但还要注意:一个字节的范围是从 -128 到 127,所以在 0x94=148 的情况下,它会在字节转换后表示为 '-108' ,所以它在数学计算中不能正常工作..

      【讨论】:

        【解决方案7】:

        这是因为 Java 中的所有内容都已签名。 0x94 (148) 大于 Byte.MAX_VALUE(2^7-1)。

        你需要的是

        public static byte[] intToByteArray(int value) {
            byte[] b = new byte[4];
            for (int i = 0; i < 4; i++) {
                int offset = (b.length - 1 - i) * 8;
                b[i] = (byte) ((value >>> offset) & 0xFF);
            }
            return b;
        }
        

        【讨论】:

        • 注意,这会完成 int 的所有 4 个字节......你只需要其中的两个。剩下的就很简单了。
        • 这有两个错误——这不是因为所有内容都已签名,而是因为 0x94 是一个 int,而不是一个字节,其次是 char 类型是无符号的,第三——该代码是一个笑话吗?如果你只是在和那个人打交道,那可能值得 +1 :) 如果你用 (byte) 沮丧的话,原来的很好
        • 0x94 是一个 int,因为它不适合字节 because bytes are signed。你是正确的,字符是无符号的 - 但是,这是规则的例外,因为它不是 intended 是一个数字 - JavaGods 决定他们的所有数字都将被签名。你能像数字一样使用它来优化字符串吗?是的你可以。它是否打算用作数字?否。Character 类是否扩展了 Number 类?不。第三,不,这段代码不是开玩笑,这是将任何 int 转换为字节数组以准确表示其位的合法方式。过去我用它来创建 TCP/IP 数据包。
        • 我试过你的代码,效果很好。感谢您帮助初学者学习 Java!
        猜你喜欢
        • 2015-04-02
        • 1970-01-01
        • 2014-02-15
        • 1970-01-01
        • 1970-01-01
        • 2019-11-17
        • 1970-01-01
        • 2010-10-16
        相关资源
        最近更新 更多