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!

Juergen
  • 12,378
  • 7
  • 39
  • 55
arakn0
  • 499
  • 5
  • 11
  • 15
  • 1
    Don't use addition (+) when recombining, you want bitwise-OR (|). – Ben Voigt Jun 25 '10 at 01:43
  • @Ben - how are they different in this case? – mdma Jun 25 '10 at 02:48
  • 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? – Ben Voigt Jun 25 '10 at 03:37

2 Answers2

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
mdma
  • 56,943
  • 12
  • 94
  • 128
  • Oh, I don't know making (byte1 & 0xFF) can make Java treat it as unsigned. Can you elaborate more on this? – Cheok Yan Cheng Jun 25 '10 at 01:30
  • Is (byte1 & 0xFF) makes it to int? – Cheok Yan Cheng Jun 25 '10 at 01:34
  • 1
    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. – mdma Jun 25 '10 at 01:43
  • @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. – SSpoke Mar 13 '14 at 07:34
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)
Liam Williams
  • 676
  • 9
  • 16