convert from short to byte and viceversa in Java
Asked Answered
N

2

3

I'm trying to convert a short into 2 bytes...and then from those 2 bytes try to get the same short value. For that, I've written this code:


        short oldshort = 700;

        byte 333= (byte) (oldshort);
        byte byte2= (byte) ((oldshort >> 8) & 0xff);

        short newshort = (short) ((byte2 << 8) + byte1);

            System.out.println(oldshort);
        System.out.println(newshort);

For the value of 700 (oldshort), newhosrt is 444. After some testing, it looksl ike \tThis code only works for some values. Like...if oldshort=50, then it will work fine..but if it is -200, or bigger values than 127 (i think) it doesn't work. I guess that there is a problem with the signed bytes, two's complement value, etc...but I can't figure out how to solve it.

Any idea?? Any native way to do this in java?? Thanks in advance!

Nejd answered 25/6, 2010 at 1:10 Comment(3)
Don't use addition (+) when recombining, you want bitwise-OR (|).Dextral
@Ben - how are they different in this case?Indeterminism
The difference is that OR saturates while ADD carries. More to the point, when you're trying to do bitwise operations, use a bitwise operator. If you want the bitwise complement of x, you wouldn't write - 1 - x, would you?Dextral
I
5

When recombining, you need to mask the byte1 to stop it being sign extended.

E.g.

    short oldshort = 700;

    byte byte1= (byte) (oldshort);
    byte byte2= (byte) ((oldshort >> 8) & 0xff);

    short newshort = (short) ((byte2 << 8) + (byte1&0xFF);

        System.out.println(oldshort);
    System.out.println(newshort);

EDIT: All operations on bytes and shorts in java are actually done as integers. So when you write +byte1, what is really happening is that the byte is first cast to an integer (sign-extended). It will still have the same value, but now has more bits. We can then mask off the bottom 8 bits to get the original 8-bits from the short - without the sign.

E.g. short =511 = 0x01FE
     // lots of 0x000's because the operations are done on 32-bit int's
     byte1 = (0x000001FE & 0x000000FF) = (0x01FE & 0xFF) = 0xFE = (byte)-2
     byte2 = 0x1

     newShort = (byte2 << 8) + (byte1 & 0xFF)
              = (0x1 << 8) + (0xFE & 0xFF)
            // since the ops are performed as int's
              = (0x00000001 << 8) + (0xFFFFFFFE & 0x000000FF)
            // 0xFFFFFFFE = -2 
              = (0x00000100) + (0x000000FE)
              = 0x000001FE
              = 511
Indeterminism answered 25/6, 2010 at 1:20 Comment(4)
Oh, I don't know making (byte1 & 0xFF) can make Java treat it as unsigned. Can you elaborate more on this?Morass
Is (byte1 & 0xFF) makes it to int?Morass
Operations on integral types smaller than an int are first implicitly cast to an int. So, before 0xFF is anded with the value, the value is first sign extended to an int, and then the mask discards all the upper bits. My edit shows this in more detail.Indeterminism
@CheokYanCheng (byte1 & 0xFF) removes any negative numbers from byte since in java a byte goes to negative 128 and up to positive 127, it can't hold a full byte like 255 which is what 0xFF means in hexadecimal. So it makes the byte1 range from 0 to 255 no negative numbers and yeah bytes can't hold 255 so you have to store it in a short,int or long anything that can hold from 0 to 255 atleast.Anoint
D
1

You could also use com.google.common.primitives.Shorts, which has methods:

  • public static byte[] toByteArray(short value)
  • public static short fromByteArray(byte[] bytes)
Drinkable answered 20/11, 2017 at 20:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.