【问题标题】:Proper way of converting C's uint32 to int in java在java中将C的uint32转换为int的正确方法
【发布时间】:2014-03-03 09:04:05
【问题描述】:

我正在构建一个由多个组件组成的项目,这些组件使用套接字在字节数组中相互通信。问题是一个组件是用 C 编写的并且支持 Unsigned 原始类型,而其他组件是用 Java 编写的并且不支持 Unsigned 类型。我正在尝试开发对 Java 中无符号类型的支持。我是 Java 新手。谁能告诉我从字节数组中解码 uint32 和 uint64 的正确方法。

我正在使用以下函数进行 int32 和 int64 的转换

public static int int32Converter(byte b[], int start) {
    return ((b[start] << 24) & 0xff000000 |(b[start + 1] << 16) & 0xff0000
            | (b[start + 2] << 8) & 0xff00 | (b[start + 3]) & 0xff);
}
public static long int64Converter(byte buf[], int start) {
    return ((buf[start] & 0xFFL) << 56) | ((buf[start + 1] & 0xFFL) << 48)
            | ((buf[start + 2] & 0xFFL) << 40)
            | ((buf[start + 3] & 0xFFL) << 32)
            | ((buf[start + 4] & 0xFFL) << 24)
            | ((buf[start + 5] & 0xFFL) << 16)
            | ((buf[start + 6] & 0xFFL) << 8)
            | ((buf[start + 7] & 0xFFL) << 0);
}

谢谢!

【问题讨论】:

    标签: java c binary type-conversion unsigned-integer


    【解决方案1】:

    您不能完全“转换”它们。您会发现最接近处理无符号值的是 Guava 的 UnsignedInteger 及其实用程序类 UnsignedInts。字节、short 和 long 也一样。

    注意你的代码,不要费心手写这些东西,使用ByteBuffer

    public static int bytesToInt(final byte[] array, final int start)
    {
         final ByteBuffer buf = ByteBuffer.wrap(array); // big endian by default
         buf.position(start);
         buf.put(array);
         return buf.position(start).getInt();
    }
    

    将 Guava 用于无符号整数:

    public static UnsignedInteger bytesToUnsignedInt(final byte[] array, final int start)
    {
             return UnsignedInteger.fromIntBits(bytesToInt(array, start);
    }
    

    但是,我怀疑UnsignedInts 确实是您想要的。 (为了比较,打印出来等)

    【讨论】:

      【解决方案2】:

      此代码会将数组中的字节复制到一个 int 中。索引 0(值 1)处的字节是 LSB。索引 3(值 15)是 MSB:

      byte[] bytes = { 1, 3, 7, 15 };
      int result = 0; 
      for (int i = 0 ; i < bytes.length ; i++) { 
          result |= bytes[i]<<(i*8); 
      }
      System.out.println(Integer.toBinaryString(result));
      

      打印:

      1111000001110000001100000001

      如果你把它改成 long 并给它一个更长的字节数组,然后你把 Integer.toBinaryString() 从 Long 改成一个,它也可以工作很长时间。

      从现在开始,您永远不要将 long/int 作为常规十进制值打印到屏幕上。需要肉眼对比时,打印二进制或十六进制值; Long.toHexString(long).

      【讨论】:

        【解决方案3】:

        如果uint32 的值永远不会超过 2^31,那么您可以将它们存储在 Java int 中。如果没有,那么您将需要一个 java Long。

        对于 uint64,如果值永远不会超过 2^63,那么您将能够使用 long,否则您将需要 BigInteger。

        在任何一种情况下,如果您要移植的算法依赖于换行(即值溢出整数并返回 0),那么您将需要添加自己的手动逻辑来处理这些情况。

        【讨论】:

          猜你喜欢
          • 2011-04-05
          • 2014-10-24
          • 2016-02-17
          • 1970-01-01
          • 2010-09-23
          • 2017-10-15
          • 1970-01-01
          • 1970-01-01
          • 2011-07-10
          相关资源
          最近更新 更多