在Java中将short转换为byte[]

56

我该如何在Java中将short(2个字节)转换为字节数组,例如:

short x = 233;
byte[] ret = new byte[2];

...

应该是这样的。但不确定。

((0xFF << 8) & x) >> 0;

编辑:

另外你也可以使用:

java.nio.ByteOrder.nativeOrder();

如何判断本机的字节顺序是大端还是小端。以下代码取自 java.io.Bits,它可以:

  • 将 byte(数组/偏移量)转换为布尔值
  • 将 byte 数组转换为 char
  • 将 byte 数组转换为 short
  • 将 byte 数组转换为 int
  • 将 byte 数组转换为 float
  • 将 byte 数组转换为 long
  • 将 byte 数组转换为 double

反之亦然。


https://dev59.com/K07Sa4cB1Zd3GeqP5amD?rq=1 - LadyDi
10个回答

84
ret[0] = (byte)(x & 0xff);
ret[1] = (byte)((x >> 8) & 0xff);

45
这是小端序。网络字节序为大端序:'byte[] arr=new byte[]{(byte)((x>>8)&0xFF),(byte)(x&0xFF)};。 - Lawrence Dol
2
这也可以起作用:byte[] arr=new byte[]{(byte)(x>>>8),(byte)(x&0xFF)} - Javier
3
为什么需要进行屏蔽操作呢?如果将 short 或 int 强制转换为 byte ,那么只有最低有效位会被使用。请问这里的屏蔽操作是为什么? - LintfordPickle
4
掩码无关紧要。将其转换为字节会截断掉高位,因此屏蔽它们是完全无意义的。 - Durandal
1
True - 它澄清了意图。当转换为较小的类型时,我通常建议 i) 如果您确定不会发生截断,请提前进行断言,或者 ii) 明确掩码。这种策略避免了来自许多分析/查找错误工具的误报。 - Alexander Gessler

49

一个更加简洁但效率较低的解决方案是:

ByteBuffer buffer = ByteBuffer.allocate(2);
buffer.putShort(value);
return buffer.array();

在以后需要进行更复杂的字节转换时,请记住这一点。ByteBuffer非常强大。


2
@abimelex,是的,这很必要。最初,在位置0和1处写入2个字节。如果不进行buffer.flip(),那么buffer.array()将读取从位置2开始的byte[]buffer.flip()将位置设置为0,限制设置为2,因此您最终得到一个从正确位置开始大小为2的数组。请查看Javadoc: http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#flip() - Gili
1
@Gili 不需要使用flip()。buffer.array()只是返回支持的byte[]数组。因此,如果您只是要使用数组获取字节表示形式,则无需翻转(flip())。但是,如果您要直接使用ByteBuffer读取字节表示形式,则应该翻转(flip())。 - Janus Varmarken
2
我们在谈论多少效率下降? - Barodapride
2
根据我的测试,我的答案比 https://dev59.com/vHI95IYBdhLWcg3wtwRe#2188682 慢了6.8倍。话虽如此,大多数情况下,ByteBuffer都足够好,并且它肯定更易读。也就是说,如果分析器显示ByteBuffer不是瓶颈,那么它慢上一百万倍也没关系。 - Gili
2
为了更语义化:ByteBuffer.allocate( Short.BYTES ).putShort(shortValue).array(); - Dávid Horváth
显示剩余2条评论

20

更有效的替代方案:

    // Little Endian
    ret[0] = (byte) x;
    ret[1] = (byte) (x >> 8);

    // Big Endian
    ret[0] = (byte) (x >> 8);
    ret[1] = (byte) x;

1
这不应该反过来吗?也就是说,第一个是小端字节序,第二个是大端字节序。 - Robby Cornelissen
1
难道最低有效字节不需要加上& 0xFF吗? - bvdb
2
@bvdb: 不需要用0xFF进行位掩码操作,因为一个字节已经是8位了。 - David
2
@David 谢谢,我再次检查过了并确认无误。 :) - bvdb

8

Kotlin中将Short转换为字节的方法适用于我:

 fun toBytes(s: Short): ByteArray {
    return byteArrayOf((s.toInt() and 0x00FF).toByte(), ((s.toInt() and 0xFF00) shr (8)).toByte())
}

1
这个问题标记为Java,而不是Kotlin。 - Gili
3
我明白,但这经常是由使用Kotlin的Android开发人员查看的。 - Serg Burlaka
同意。@SergBurlaka,你应该发一篇单独的帖子并自己回答它,以获得额外的积分,并让更多的Kotlin开发者看到你的答案。 - Ryan Tremblay

7
弄清楚了,这是:

弄清楚了,它是:

public static byte[] toBytes(short s) {
    return new byte[]{(byte)(s & 0x00FF),(byte)((s & 0xFF00)>>8)};
}

5

这里提到了几种方法,但哪一种是最好的呢?以下是一些证明:以下3种方法在所有short值上产生相同的输出

  // loops through all the values of a Short
  short i = Short.MIN_VALUE;
  do
  {
    // method 1: A SIMPLE SHIFT
    byte a1 = (byte) (i >> 8);
    byte a2 = (byte) i;

    // method 2: AN UNSIGNED SHIFT
    byte b1 = (byte) (i >>> 8);
    byte b2 = (byte) i;

    // method 3: SHIFT AND MASK
    byte c1 = (byte) (i >> 8 & 0xFF);
    byte c2 = (byte) (i & 0xFF);

    if (a1 != b1 || a1 != c1 ||
        a2 != b2 || a2 != c2)
    {
      // this point is never reached !!
    }
  } while (i++ != Short.MAX_VALUE);

结论:少即是多?
byte b1 = (byte) (s >> 8);
byte b2 = (byte) s;

(正如其他答案所提到的,要注意LE/BE。)


3

这取决于你想要如何表示:

  • 大端序还是小端序?这将决定你放置字节的顺序。

  • 你想使用2的补码还是其他方式来表示负数?应该使用与Java中short类型具有相同范围的方案,以获得1对1的映射。

对于大端序,转换应该按以下方式进行:ret[0] = x/256; ret[1] = x%256;


1
public short bytesToShort(byte[] bytes) {
     return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
}

public byte[] shortToBytes(short value) {
    byte[] returnByteArray = new byte[2];
    returnByteArray[0] = (byte) (value & 0xff);
    returnByteArray[1] = (byte) ((value >>> 8) & 0xff);
    return returnByteArray;
}

0

短整型转字节

short x=17000;    
byte res[]=new byte[2];    
res[i]= (byte)(((short)(x>>7)) & ((short)0x7f) | 0x80 );    
res[i+1]= (byte)((x & ((short)0x7f)));

将byte转换为short

short x=(short)(128*((byte)(res[i] &(byte)0x7f))+res[i+1]);

0
以下方法将以BIG_ENDIAN顺序从字节数组的任意位置读取和写入短整型值。该代码比使用ByteBuffer更高效,因为不会发生堆分配。
//
// Write BIG_ENDIAN short to an array at given index.
// Same, but more efficient than: 
//   ByteBuffer.wrap(arr).order(ByteOrder.BIG_ENDIAN).putShort(idx, val)
//
static void putShort(short val, byte[] arr, int idx) {
    arr[idx]     = (byte) (val >>> 8);
    arr[idx + 1] = (byte) val;
}

//
// Read BIG_ENDIAN short from an array at given index.
// Same, but more efficient than: 
//   ByteBuffer.wrap(arr).order(ByteOrder.BIG_ENDIAN).getShort(idx)
//
static short getShort(byte[] arr, int idx) {
    return (short) (               // low two bytes of int composed
         (0xff & arr[idx]) << 8    // from high byte
       | (0xff & arr[idx + 1])     // and low byte
    );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接