【问题标题】:how to read signed int from bytes in java?如何从java中的字节读取带符号的int?
【发布时间】:2011-11-01 17:48:23
【问题描述】:

我有一个规范,它读取接下来的两个字节是有符号整数。

要在 java 中阅读,我有以下内容

当我使用以下代码在 java 中读取签名 int 时,我得到的值为 65449

无符号计算逻辑

int a =(byte[1] & 0xff) <<8

int b =(byte[0] & 0xff) <<0

int c = a+b 

我认为这是错误的,因为如果 i 和 0xff 我得到一个无符号等价物

所以我删除了 & 0xff 和下面给出的逻辑

int a = byte[1] <<8
int b = byte[0] << 0
int c = a+b
which gives me the value -343
byte[1] =-1
byte[0]=-87

我试图用规范读取的方式来抵消这些值,但这看起来不对。因为堆的大小不属于这个。

在java中进行有符号整数计算的正确方法是什么?

规范是这样的

somespec() { xtype 8 uint8 xStyle 16 int16 } xStyle :一个有符号整数,表示从 Widget() 结构的开头到 xStyle() 结构的开头的偏移量(以字节为单位),表示由页面小部件定义的继承样式以及专门应用于此小部件的样式.

【问题讨论】:

  • 你能展示一个输入和期望结果的例子吗?不清楚..
  • 我使用规范从流中读取。我根据规范读取了两个字节,当我在字节数组中读取转换为单个字节时的值是 byte[1]=-1 和 byte[0]=-87 说在包含两个字节的字节数组中。规范将这两个字节标记为有符号整数,我不知道正确的输出是什么。

标签: java binary


【解决方案1】:

如果您的值是带符号的 16 位,则需要 short 而 int 是 32 位,它也可以保存相同的值,但不那么自然。

看来您想要一个有符号的 little endian 16 位值。

byte[] bytes = 
short s = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();

short s = (short) ((bytes[0] & 0xff) | (bytes[1] << 8));

顺便说一句:您可以使用 int,但它不是那么简单。

// to get a sign extension.
int i = ((bytes[0] & 0xff) | (bytes[1] << 8)) << 16 >> 16;

int i = (bytes[0] & 0xff) | (short) (bytes[1] << 8));

【讨论】:

    【解决方案2】:

    假设 bytes[1] 是 MSB,bytes[0] 是 LSB,并且您希望答案是 16 位有符号整数:

    short res16 = ((bytes[1] << 8) | bytes[0]);
    

    然后得到一个32位有符号整数:

    int res32 = res16;  // sign extends.
    

    顺便说一句,规范应该说明两个字节中哪个是MSB,哪个是LSB。如果没有,如果没有任何例子,你就不能实现它!


    在规范的某个地方,它会说明“int16”是如何表示的。粘贴那部分。或者粘贴一个指向规范的链接,以便我们自己阅读。

    【讨论】:

    • 请在主查询中查看我的编辑,我已经给出了规范的读取方式
    【解决方案3】:

    看看DataInputStream.readInt()。您可以从那里编写代码,也可以只使用 DataInputStream:用它包装您的输入流,然后轻松读取类型化数据。

    为方便起见,这是代码:

    public final int readInt() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        int ch3 = in.read();
        int ch4 = in.read();
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    }
    

    【讨论】:

    • 这读取的是一个大端序的 32 位值,我相信 OP 想要一个小端序的 16 位值。
    【解决方案4】:

    我现在不能编译它,但我会编译(假设 byte1byte0 是字节类型)。

     int result = byte1;
     result = result << 8;
     result = result | byte0;  //(binary OR)
     if (result & 0x8000 == 0x8000) { //sign extension
       result = result | 0xFFFF0000;
     }
    

    如果byte1byte0 是整数,则需要将`&0xFF

    更新,因为 Java 将 if 的表达式强制为布尔值

    【讨论】:

    • 如果我这样做,我会得到 -87 的偏移量,我会试试这个,看看我是否能够读取堆中的值。另外,你能帮我验证一下我应该怎么做阅读此规范 somespec() { xtype 8 uint8 xStyle 16 int16 } xStyle :一个有符号整数,表示从 Widget() 结构的开头到表示继承样式的 xStyle() 结构的开头的偏移量(以字节为单位)由页面小部件以及专门应用于此小部件的样式定义。
    【解决方案5】:

    你有办法为给定的输入找到正确的输出吗? 从技术上讲,一个 int 大小是 4 个字节,所以只有 2 个字节你无法到达符号位。

    【讨论】:

    • somespec() { xtype 8 uint8 pwStyle 16 int16 } 一个有符号整数,表示从 Widget() 结构开始到 xStyle() 结构开始的偏移量(以字节为单位),表示由页面小部件定义的继承样式以及专门应用于此小部件的样式。
    【解决方案6】:

    我在读取 MIDI 文件时遇到了同样的问题。 MIDI 文件具有带符号的 16 位和带符号的 32 位整数。在 MIDI 文件中,最重要的字节在前(大端)。

    这就是我所做的。它可能很粗糙,但它保持了标志。如果最低有效字节在前(小端),则反转索引的顺序。

    pos 是字节数组中数字开始的位置。

    length 是整数的长度,2 或 4。是的,2 字节整数是短整数,但我们都使用整数。

    private int convertBytes(byte[] number, int pos, int length) {
        int output = 0;
        if (length == 2) {
            output = ((int) number[pos]) << 24;
            output |= convertByte(number[pos + 1]) << 16;
            output >>= 16;
        } else if (length == 4) {
            output = ((int) number[pos]) << 24;
            output |= convertByte(number[pos + 1]) << 16;
            output |= convertByte(number[pos + 2]) << 8;
            output |= convertByte(number[pos + 3]);
        }
        return output;
    }
    
    private int convertByte(byte number) {
        return (int) number & 0xff;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      相关资源
      最近更新 更多