convert from short to byte and viceversa in Java - java

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!

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

You could also use com.google.common.primitives.Shorts, which has methods:
public static byte[] toByteArray(short value)
public static short fromByteArray(byte[] bytes)

Related

How to convert 2 bytes from byte[] to a Char / short (2 bytes)?

My goal is to convert 2 bytes to a Char.
The input will be from a byte[] then converted to char. My initial strategy was to use bitwise operations.
My expected result: 0xFF << 8 | 0xFF equals to 0xFFFF. It does. But, in practice it does not because before the bitwise operations, I need to store the data in byte[].
My actual result: Due to the way I access the data. (byte) 0xFF << 8 | (byte) 0xFF will equal to -1.
byte[] bytes = new byte[]{(byte) 0xFF, (byte) 0xFF};
int integer = bytes[0] << 8 | bytes[1]; // -1 or 0xFFFFFFFF
You need:
int integer = (bytes[0] & 0xff) << 8 | (bytes[1] & 0xff);
Which gives the expected value of 65535.

Reading an int in java as a binary sequence using ByteBuffer

I'm trying to read an int (32 bits) to a bytebuffer object.
I've used the method "Bytebuffer.allocate(4)", and I wish to take every 8 bits(1 byte) of the given int, into the bytebuffer object.
How can I do this?
(I need to use it in order to convert every Byte(8 bits) to a number between 0-255)
Edit: I'm just trying to get the 32 bit of an int(it's for a school project and the assignment said specifcly "we will use int not as a number, but as a binary sequence of 32 bits" and that's what I'm trying to do but with absolutely no success.
Thanks.
Use simple shift and mask operations:
byte b1 = n & 0xFf;
byte b2 = (n >> 8) & 0xFF;
byte b3 = (n >> 16) & 0xFF;
byte b4 = (n >> 24) & 0xFF;

Issues when converting bytes to integers (Java specific?)

I'm a bit confused regarding a conversion from bytes to integers. Consider the following code:
byte[] data = new byte[] { 0, (byte) 0xF0 };
int masked = data[0] << 8 & 0xFF | data[1] & 0xFF; //240
int notMasked = data[0] << 8 | data[1]; //-16
Because bytes in java are signed, data[1] is not 240 decimal, but rather the 2's complement, -16. However, it should still be, in binary: 0x11110000 so, why do I need to do data[1] & 0xFF ?
Is Java converting everything to Integer before passing it to the | operator? Why does &0xFF make a difference then?
Java bytes are signed (unfortunately) - so when you promote the value to an int in order to perform the bitwise |, it ends up being sign-extended as 0xFFFFFFF0. That then messes up the | with data[0]. The masking with & 0xff converts it to an integer value of 240 (just 0x000000F0) instead.
However, you've stlil got a problem. This code:
int masked = data[0] << 8 & 0xFF | data[1] & 0xFF;
should be:
int masked = ((data[0] & 0xff) << 8) | (data[1] & 0xFF);
... otherwise you're masking after the shift, which won't work. I've added brackets because I'm never sure of the predence of &, << and |...
It is similar to a known "puzzle"
byte x = -1;
x = x >>>= 1;
System.out.println(x);
produces
-1
No shift? This is because before compiling arithemtic / shift / comparison expressions javac promotes byte (as well as short and char) to int or to long (if there is any long in the expression), so it works as follows
x -> int = 0xFFFFFFFF; 0xFFFFFFF >>> 1 = 0x7FFFFFF; (byte)0x7FFFFFF -> 0xFF

Java - write the first byte of an int

Ok, so I have searched and searched and nothing worked...
I have this array of int, each int occupies only the low order byte. For instance, I have
data[0] = Ox52
data[1] = Oxe4
data[2] = Ox18
data[3] = Oxcb
I want that the standard output contains exactly those bytes (or in other words, if I write this in a file and I examine the file with a Hex editor, I should see):
52e418cb
How can I do that?
Thank you for your help
The correct way of doing this is to shift the bytes according to their desired position and then stitch them together using the OR operator. But, you should also perform a bit mask on the lower 8 bits of the byte before shifting it. This is needed because a byte is first converted to an int (before the shifting is done). This is no big deal, but when the highest bit is 1 (i.e.: the byte is negative), your integer will become negative as well, which causes all the leading bits to be set on 1.
So:
(byte) 10000000 = (int) 11111111 11111111 11111111 10000000
Using this negative int value with the OR operator will cause a wrong result. So, the working line is this one:
((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16) | ((data[2] & 0xFF) << 8) | (data[3] & 0xFF)
The following seems to work fine. I'm using the OutputStream.write(int) method.
int[] ints = new int[] { 0x52, 0xe4, 0x18, 0xcb };
FileOutputStream os = new FileOutputStream(new File("/tmp/x"));
for (int i : ints) {
os.write(i);
}
os.close();
Results:
> hexdump /tmp/x
0000000 52 e4 18 cb
Just shift and OR them together before writing them to the file/output:
(data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]

Convert a byte array to integer in Java and vice versa

I want to store some data into byte arrays in Java. Basically just numbers which can take up to 2 Bytes per number.
I'd like to know how I can convert an integer into a 2 byte long byte array and vice versa. I found a lot of solutions googling but most of them don't explain what happens in the code. There's a lot of shifting stuff I don't really understand so I would appreciate a basic explanation.
Use the classes found in the java.nio namespace, in particular, the ByteBuffer. It can do all the work for you.
byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1
ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }
byte[] toByteArray(int value) {
return ByteBuffer.allocate(4).putInt(value).array();
}
byte[] toByteArray(int value) {
return new byte[] {
(byte)(value >> 24),
(byte)(value >> 16),
(byte)(value >> 8),
(byte)value };
}
int fromByteArray(byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, |
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
return ((bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8 ) |
((bytes[3] & 0xFF) << 0 );
}
When packing signed bytes into an int, each byte needs to be masked off because it is sign-extended to 32 bits (rather than zero-extended) due to the arithmetic promotion rule (described in JLS, Conversions and Promotions).
There's an interesting puzzle related to this described in Java Puzzlers ("A Big Delight in Every Byte") by Joshua Bloch and Neal Gafter . When comparing a byte value to an int value, the byte is sign-extended to an int and then this value is compared to the other int
byte[] bytes = (…)
if (bytes[0] == 0xFF) {
// dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}
Note that all numeric types are signed in Java with exception to char being a 16-bit unsigned integer type.
You can also use BigInteger for variable length bytes. You can convert it to long, int or short, whichever suits your needs.
new BigInteger(bytes).intValue();
or to denote polarity:
new BigInteger(1, bytes).intValue();
To get bytes back just:
new BigInteger(bytes).toByteArray()
Although simple, I just wanted to point out that if you run this many times in a loop, this could lead to a lot of garbage collection. This may be a concern depending on your use case.
A basic implementation would be something like this:
public class Test {
public static void main(String[] args) {
int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
byte[] output = new byte[input.length * 2];
for (int i = 0, j = 0; i < input.length; i++, j+=2) {
output[j] = (byte)(input[i] & 0xff);
output[j+1] = (byte)((input[i] >> 8) & 0xff);
}
for (int i = 0; i < output.length; i++)
System.out.format("%02x\n",output[i]);
}
}
In order to understand things you can read this WP article: http://en.wikipedia.org/wiki/Endianness
The above source code will output 34 12 78 56 bc 9a. The first 2 bytes (34 12) represent the first integer, etc. The above source code encodes integers in little endian format.
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
int val = 0;
if(length>4) throw new RuntimeException("Too big to fit in int");
for (int i = 0; i < length; i++) {
val=val<<8;
val=val|(bytes[i] & 0xFF);
}
return val;
}
As often, guava has what you need.
To go from byte array to int: Ints.fromBytesArray, doc here
To go from int to byte array: Ints.toByteArray, doc here
Someone with a requirement where they have to read from bits, lets say you have to read from only 3 bits but you need signed integer then use following:
data is of type: java.util.BitSet
new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3
The magic number 3 can be replaced with the number of bits (not bytes) you are using.
i think this is a best mode to cast to int
public int ByteToint(Byte B){
String comb;
int out=0;
comb=B+"";
salida= Integer.parseInt(comb);
out=out+128;
return out;
}
first comvert byte to String
comb=B+"";
next step is comvert to a int
out= Integer.parseInt(comb);
but byte is in rage of -128 to 127 for this reasone, i think is better use rage 0 to 255 and you only need to do this:
out=out+256;

Categories

Resources