56

How can I convert a short (2 bytes) to a byte array in Java, e.g.

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

...

it should be something like this. But not sure.

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

EDIT:

Also you can use:

java.nio.ByteOrder.nativeOrder();

To discover to get whether the native bit order is big or small. In addition the following code is taken from java.io.Bits which does:

  • byte (array/offset) to boolean
  • byte array to char
  • byte array to short
  • byte array to int
  • byte array to float
  • byte array to long
  • byte array to double

And visa versa.

Hugh
  • 1,182
  • 2
  • 9
  • 14
  • http://stackoverflow.com/questions/3114935/convert-from-short-to-byte-and-viceversa-in-java?rq=1 – LadyDi Jun 16 '14 at 17:23

10 Answers10

84
ret[0] = (byte)(x & 0xff);
ret[1] = (byte)((x >> 8) & 0xff);
Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • 45
    That's little endian, though. Network byte-order is big endian: 'byte[] arr=new byte[]{(byte)((x>>8)&0xFF),(byte)(x&0xFF)}; – Lawrence Dol Feb 03 '10 at 01:31
  • 2
    This could work too `byte[] arr=new byte[]{(byte)(x>>>8),(byte)(x&0xFF)}` – Javier Mar 27 '12 at 22:57
  • 3
    can I ask here, why is the masking needed if casting a short or int to byte will only ever take the LSB anyway?Thanks – LintfordPickle Aug 29 '13 at 19:45
  • 4
    The masking is superflous. The cast to byte truncates away the upper bits anyway, so masking them out is completly pointless. – Durandal Oct 02 '14 at 18:34
  • 1
    True - it clarifies intent though. When casting to a smaller type, I would normally recommend to i) assert upfront if you're sure no truncation will occur, or ii) explicitly mask. This strategy avoids false positives from plenty of analysis/findbug tools. – Alexander Gessler Oct 02 '14 at 22:41
49

A cleaner, albeit far less efficient solution is:

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

Keep this in mind when you have to do more complex byte transformations in the future. ByteBuffers are very powerful.

Gili
  • 86,244
  • 97
  • 390
  • 689
  • 2
    @abimelex, yes it is necessary. Initially you write 2 bytes at position 0, 1. If you don't `buffer.flip()` then `buffer.array()` will read `byte[]` starting at position 2. `buffer.flip()` sets the position to 0 and the limit to 2 so you end up with an array of size 2 starting at the right position. Take a look at the Javadoc: http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#flip() – Gili Nov 18 '13 at 16:30
  • 1
    @Gili No, the flip() is not necessary. buffer.array() simply returns the backing byte[] array. So if you're simply going to get the byte representation using the array, there is no need to flip(). However, if you are going to read the byte representation using the ByteBuffer directly, you should flip(). – Janus Varmarken Oct 02 '14 at 18:04
  • @jvmk, on second glance. You're right. I've corrected the answer. – Gili Oct 02 '14 at 18:13
  • 2
    How much less efficient are we talking? – Barodapride Oct 03 '14 at 22:43
  • 2
    @Barodapride: According to my own tests, my answer is 6.8 times slower than http://stackoverflow.com/a/2188682/14731. That said, most of the time `ByteBuffer` will be "good enough" and it is certainly much more readable. Meaning, it doesn't matter if `ByteBuffer` is a million times slower so long the profiler says that it's not a bottleneck. – Gili Oct 05 '14 at 04:40
  • 1
    I made a one-liner of this for a utility method: `return ByteBuffer.allocate(2).putShort(shortValue).array();` – mharper Jun 29 '15 at 21:02
  • 2
    Too be more semantic: `ByteBuffer.allocate(` **`Short.BYTES`** `).putShort(shortValue).array();` – Dávid Horváth Dec 28 '20 at 10:53
20

An alternative that is more efficient:

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

    // Big Endian
    ret[0] = (byte) (x >> 8);
    ret[1] = (byte) x;
David
  • 3,957
  • 2
  • 28
  • 52
8

Short to bytes convert method In Kotlin works for me:

 fun toBytes(s: Short): ByteArray {
    return byteArrayOf((s.toInt() and 0x00FF).toByte(), ((s.toInt() and 0xFF00) shr (8)).toByte())
}
Serg Burlaka
  • 2,351
  • 24
  • 35
7

Figured it out, its:

public static byte[] toBytes(short s) {
    return new byte[]{(byte)(s & 0x00FF),(byte)((s & 0xFF00)>>8)};
}
Hugh
  • 1,182
  • 2
  • 9
  • 14
5

Several methods have been mentioned here. But which one is the best? Here follows some proof that the following 3 approaches result in the same output for all values of a 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);

Conclusion: less is more ?

byte b1 = (byte) (s >> 8);
byte b2 = (byte) s;

(As other answers have mentioned, watch out for LE/BE).

bvdb
  • 22,839
  • 10
  • 110
  • 123
3

It depends how you want to represent it:

  • big endian or little endian? That will determine which order you put the bytes in.

  • Do you want to use 2's complement or some other way of representing a negative number? You should use a scheme that has the same range as the short in java to have a 1-to-1 mapping.

For big endian, the transformation should be along the lines of: ret[0] = x/256; ret[1] = x%256;

abc
  • 1,352
  • 1
  • 9
  • 13
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;
}
Scott Izu
  • 2,229
  • 25
  • 12
0

short to byte

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 to short

short x=(short)(128*((byte)(res[i] &(byte)0x7f))+res[i+1]);
Irshad
  • 3,071
  • 5
  • 30
  • 51
0

Following methods will read and write short value, in BIG_ENDIAN ordering, to/from arbitary placement in byte array. The code is more efficient than using ByteBuffer as no heap allocation occurs.

//
// 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
    );
}
Talijanac
  • 1,087
  • 9
  • 20