Convert short to byte[] in Java
Asked Answered
E

10

58

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.

Equalizer answered 2/2, 2010 at 23:51 Comment(1)
#3115435Kevinkevina
A
87
ret[0] = (byte)(x & 0xff);
ret[1] = (byte)((x >> 8) & 0xff);
Alienation answered 2/2, 2010 at 23:56 Comment(5)
That's little endian, though. Network byte-order is big endian: 'byte[] arr=new byte[]{(byte)((x>>8)&0xFF),(byte)(x&0xFF)};Opuscule
This could work too byte[] arr=new byte[]{(byte)(x>>>8),(byte)(x&0xFF)}Mazuma
can I ask here, why is the masking needed if casting a short or int to byte will only ever take the LSB anyway?ThanksThreadbare
The masking is superflous. The cast to byte truncates away the upper bits anyway, so masking them out is completly pointless.Semaphore
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.Alienation
L
50

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.

Larch answered 24/6, 2011 at 19:39 Comment(7)
@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: docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#flip()Larch
@Larch 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().Sideling
@jvmk, on second glance. You're right. I've corrected the answer.Larch
How much less efficient are we talking?Mcintyre
@Barodapride: According to my own tests, my answer is 6.8 times slower than https://mcmap.net/q/328917/-convert-short-to-byte-in-java. 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.Larch
I made a one-liner of this for a utility method: return ByteBuffer.allocate(2).putShort(shortValue).array();Pires
Too be more semantic: ByteBuffer.allocate( Short.BYTES ).putShort(shortValue).array();Screenplay
P
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;
Pentode answered 24/5, 2013 at 11:41 Comment(4)
Shouldn't that be the other way around? I.e. the first is little-endian and the second is big-endian.Buffalo
Isn't there a & 0xFF necessary for the least significant byte ?Kirsti
@bvdb: no need to bitmask with 0xFF since a byte is 8-bit already.Pentode
@Pentode thanks, double checked it and can confirm. :)Kirsti
R
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())
}
Randers answered 20/12, 2017 at 11:45 Comment(3)
This question is tagged for Java, not Kotlin.Larch
@Larch i know, but this is often looking by Android developers witch using KotlinRanders
Seconded. @SergBurlaka you should make a separate post and answer it yourself for the extra points and so your answer is seen by more Kotlin devs.Regatta
E
7

Figured it out, its:

public static byte[] toBytes(short s) {
    return new byte[]{(byte)(s & 0x00FF),(byte)((s & 0xFF00)>>8)};
}
Equalizer answered 2/2, 2010 at 23:57 Comment(0)
K
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).

Kirsti answered 17/8, 2015 at 11:13 Comment(0)
N
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;

Nugget answered 2/2, 2010 at 23:59 Comment(0)
S
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;
}
Schoenberg answered 8/8, 2013 at 6:27 Comment(0)
P
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]);
Poirer answered 17/11, 2015 at 4:38 Comment(0)
D
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
    );
}
Diamond answered 7/7, 2023 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.