Unsigned Shift Operator(>>>) and convert int to byte arrays in java - java

I want to convert integer to byte[] in java. And I did some research and found the code
public byte[] integerToBytes (int i) {
byte[] result = new byte[4];
result[0] = (byte) (i >>> 24);
result[1] = (byte) (i >>> 16);
result[2] = (byte) (i >>> 8);
result[3] = (byte) (i /*>> 0*/);
return result;
}
I'm pretty sure the code is right cause it passes the tests. However, I'm a little bit confused.
Suppose the integer is 36666666. And binary representation is 10001011110111110100101010.I can understand why it is true for result[0] since after the shift, it becomes 10001011(0x22).However,for result[1],after the shift,it becomes 1000101111011111(0x22F7).
But what I really want is just 0xF7.
Can someone explain this to me or I understand this code in a wrong way?
Cheers

The reason result[1] and others are just the lowest eight bits is due to the the cast to a byte performed on each assignment. Casting an int like 0x22F7 to a byte cuts off the top 3 bytes and leaves the least significant byte to be assigned to the new variable. Thus 0x22f7 becomes just 0xf7. Hope this helps.

Related

How can I concatenate two bytes in java?

I have an integer called writePos that takes a value between [0,1023]. I need to store it in the last two bytes of a byte array called bucket. So, I figure I need to represent it as a concatenation of the array's last two bytes.
How would I go about breaking down writePos into two bytes that, when concatenated and cast into an int, produces writePos again?
How would I go about concatenating once I get it broken down into the bytes?
This would be covered high-level by a ByteBuffer.
short loc = (short) writeLocation;
byte[] bucket = ...
int idex = bucket.length - 2;
ByteBuffer buf = ByteBuffer.wrap(bucket);
buf.order(ByteOrder.LITTLE__ENDIAN); // Optional
buf.putShort(index, loc);
writeLocation = buf.getShort(index);
The order can be specified, or left to the default (BIG_ENDIAN).
The ByteBuffer wraps the original byte array, and changes to ByteBuffer effect on the byte array too.
One can use sequential writing and reading an positioning (seek), but here I use overloaded methods for immediate positioning with index.
putShort writes to the byte array, modifying two bytes, a short.
getShort reads a short from the byte array, which can be put in an int.
Explanation
A short in java is a two-byte (signed) integral number. And that is what is meant. The order is whether LITTLE_ENDIAN: least significant byte first (n % 256, n / 256) or big endian.
Bitwise operations.
To byte:
byte[] bytes = new byte[2];
// This uses a bitwise and (&) to take only the last 8 bits of i
byte[0] = (byte)(i & 0xff);
// This uses a bitwise and (&) to take the 9th to 16th bits of i
// It then uses a right shift (>>) then move them right 8 bits
byte[1] = (byte)((i & 0xff00) >> 8);from byte:
To go back the other way
// This just reverses the shift, no need for masking.
// The & here is used to handle complications coming from the sign bit that
// will otherwise be moved as the bytes are combined together and converted
// into an int
i = (byte[0] & 0xFF)+(byte[1] & 0xFF)<<8;
There is a working example here of some of the conversions that you can play around with:
http://ideone.com/eRzsun
You need to split the integer into two bytes. The high and the low byte. Following your description it's stored as bug endian in the array.
int writeLocation = 511;
byte[] bucket = new byte[10];
// range checks must be done before
// bitwise right rotation by 8 bits
bucket[8] = (byte) (writeLocation >> 8); // the high byte
bucket[9] = (byte) (writeLocation & 0xFF); // the low byte
System.out.println("bytes = " + Arrays.toString(bucket));
// convert back the integer value 511 from the two bytes
bucket[8] = 1;
bucket[9] = (byte) (0xFF);
// the high byte will bit bitwise left rotated
// the low byte will be converted into an int
// and only the last 8 bits will be added
writeLocation = (bucket[8] << 8) + (((int) bucket[9]) & 0xFF);
System.out.println("writeLocation = " + writeLocation);

Correctly convert decimal value to byte value

I need to convert decimal value like
int dec = 129;
into a byte value like
byte frame2 = (byte) 129;
but as you might already have guessed, it converts into an unexpected value. I want the byte value to be literally 129 instead of -127 (value of frame2).
How could you achieve it in Java? I would appreciate an explanation as well.
Thanks
You can't and most likely you don't need to. a byte is -128 to 127 by definition. However you can store any 256 different values in a byte if you want with encoding.
byte b = (byte) 129;
int i = b & 0xff; // == 129
or
byte b = (byte) (129 + Byte.MIN_VALUE);
int i = b - Byte.MIN_VALUE; // also 129.
I need to convert decimal value like
Stop right there. There is no such thing as a 'decimal value'. There are values, which are held in 2s-complement, and there are decimal representations.
int dec = 129;
That will be stored as 129(10), or 81(16).
into a byte value like
byte frame2 = (byte) 129;
The result of that will be -127, because bytes are signed in Java and your value sets the sign bit.
If you want to use the value as though it was 129, use (frame2 & 0xff). However it is quite likely that you don't need to do that at all.
Your question is actually about sign-extension of bytes in Java: it has nothing to do with decimals at all.

Converting from byte array to short producing wrong negative value

It's been a while since I've done operations at the bit/byte level so please forgive me if this is simple.
I'm receiving data over a TCP socket in a Java application from an embedded device. The data is little endian (least significant byte first) and I'm currently trying to grab short values out of an array of data. To do this, I'm using the following code:
byte[] valBytes = {data[0], data[1]};
short val = EndianArrayUtils.getShortFromLittleEndianRange(valBytes);
This works fine for positive numbers, but when the short should be -1, I'm getting -2 instead. The data that produces -2 is:
byte[] valBytes = {(byte)0xff, (byte)0xff};
short val = EndianArrayUtils.getShortFromLittleEndianRange(valBytes);
Am I missing something? -1 in two's complement should be 11111111 11111111 correct?
Edit
I completely forgot that I was the one that actually wrote EndianArrayUtils. The code for the getShortFromLittleEndianRange method is
public static short getShortFromLittleEndianRange(byte[] range){
return (short)((short)(range[1] >> 8) + (short)(range[0]));
}
Obviously there's something wrong with how that's operating on negative numbers.
I would use ByteBuffer
byte[] valBytes = {(byte)0xff, (byte)0xff};
short s = ByteBuffer.wrap(valBytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
System.out.println(s);
prints
-1
If you read into a ByteBuffer you don't need the byte[] at all.
To fix your example
public static short getShortFromLittleEndianRange(byte[] range){
return (short)((range[1] << 8) + (range[0] & 0xff));
}

How to String-Integer signed value to 2 byte array on the Davik VM?

Given a integer value from a string, I want to convert it to 2 byte signed integer.
BigInteger does the job, but I don't know how to grant 2 bytes...
public void handleThisStringValue(String x, String y){
BigInteger bi_x = new BigInteger(x, 10);
BigInteger bi_y = new BigInteger(y, 10);
byte[] byteX = bi_x.toByteArray();
byte[] byteY = bi_y.toByteArray();
}
I noticed that BigInteger.toByteArray() handles negative values which is suitable for me.
Then I need to read those values (negative and positive ones), or saying convert byte[2] to signed int. Any suggestion?
Well, your questions still lacks certain information.
First, Java integers are 32-bit long, so they will not fit into a 2-byte array, you need a 4-byte array, otherwise you are actually dealing with short data type, which is 16-bit long.
Also, not sure if you need to deal with any kind of byte ordering (little endian, big endian).
At any rate, assuming that you are using integers that only fit in 16-bits and big endian byte ordering, you could do something as follows to create the byte array:
public static byte[] toByteArray(String number){
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(Integer.parseInt(number));
return Arrays.copyOfRange(buffer.array(), 2, 4); //asumming big endian
}
And as follows to convert it back:
public static int toInteger(byte[] payload){
byte[] data = new byte[4];
System.arraycopy(payload, 0, data, 2, 2);
return ByteBuffer.wrap(data).getInt();
}
You can also change the byte order of the ByteBuffer with the ByteBuffer.order method.
I used it as follows:
byte[] payload = toByteArray("255");
int number = toInteger(payload);
System.out.println(number);
Output is 255
int x = bs[0] | ((int)bs[1] << 8);
if (x >= 0x8000) x -= 0x10000;
// Reverse
bs[0] = (byte)(x & 0xFF);
bs[1] = (byte)((x >> 8) & 0xFF);
You can make the inverse:
new BigInteger(byteX);
new BigInteger(byteY);
It's exactly what you want, and then you can use .intvalue() to get it as an int
The solution is simple, based in posts I found here (thank you for all):
Remember that I wanted a 2 byte integer... so it is a Short!
String val= "-32";
short x = Short.parseShort(val);
byte[] byteX = ByteBuffer.allocate(2).putShort(x).array();
... and it works!
Then, I'm using BigInteger to read it back!
int x1 = new BigInteger(byteX).intValue();
or
short x2 = new BigInteger(x).shortValue();

Convert long to byte array and add it to another array

I want to change a values in byte array to put a long timestamp value in in the MSBs. Can someone tell me whats the best way to do it. I do not want to insert values bit-by-bit which I believe is very inefficient.
long time = System.currentTimeMillis();
Long timeStamp = new Long(time);
byte[] bArray = new byte[128];
What I want is something like:
byte[0-63] = timeStamp.byteValue();
Is something like this possible . What is the best way to edit/insert values in this byte array. since byte is a primitive I dont think there are some direct implementations I can make use of?
Edit:
It seems that System.currentTimeMillis() is faster than Calendar.getTimeInMillis(), so replacing the above code by it.Please correct me if wrong.
There are multiple ways to do it:
Use a ByteBuffer (best option - concise and easy to read):
byte[] bytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(someLong).array();
You can also use DataOutputStream (more verbose):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeLong(someLong);
dos.close();
byte[] longBytes = baos.toByteArray();
Finally, you can do this manually (taken from the LongSerializer in Hector's code) (harder to read):
byte[] b = new byte[8];
for (int i = 0; i < size; ++i) {
b[i] = (byte) (l >> (size - i - 1 << 3));
}
Then you can append these bytes to your existing array by a simple loop:
// change this, if you want your long to start from
// a different position in the array
int start = 0;
for (int i = 0; i < longBytes.length; i ++) {
bytes[start + i] = longBytes[i];
}
If you want to really get under the hood...
public byte[] longToByteArray(long value) {
return new byte[] {
(byte) (value >> 56),
(byte) (value >> 48),
(byte) (value >> 40),
(byte) (value >> 32),
(byte) (value >> 24),
(byte) (value >> 16),
(byte) (value >> 8),
(byte) value
};
}
For me ByteBuffer and other utils are expensive from time perspective. Here are 2 methods that you can use:
// first method (that is using the second method), it return the array allocated and fulfilled
public byte[] longToByteArray(long value)
{
byte[] array = new byte[8];
longToByteArray(value,array,0);
return array;
}
// this method is useful if you have already allocated the buffer and you want to write the long a specific location in the array.
public void longToByteArray(long value, byte[] array, int startFrom)
{
for (int i=7; i>=0; i--)
{
array[startFrom+7-i] = (byte) (value >> i*8);
}
}
It doesn't look like you can slice a byte array to insert something into a subset without doing it byte by byte. Look at Grab a segment of an array in Java without creating a new array on heap . Basically what I would do is set create a 64 byte array and set the time to it then append a blank 64 byte array to it. Or just do it byte by byte.
I am updating this post because I have just announced a pre-release version of a library that will convert longs to byte arrays (and back again). The library is very small and will convert any java primitive to a byte array.
http://rschilling.wordpress.com/2013/09/26/pre-release-announcement-pend-oreille/
http://code.google.com/p/pend-oreille/
If you use it you can do things like convert long arrays to byte arrays:
Double[] doubles = new Double[1000];
for (int i = 2; i < 1002; i++) {
doubles[i - 2] = (double) i;
}
byte[] resultBytes1 = (byte[]) new PrimitiveHelper(PrimitiveUtil.unbox(doubles))
.asType(byte[].class);
You can also convert a single long value as well.
byte[] resultBytes1 = (byte[]) new PrimitiveHelper(1000l)
.asType(byte[].class);
Feel free to provide some feedback.
Update on October 4, 2013:
I've now released the production of the library http://rschilling.wordpress.com/2013/10/04/pend-oreille-official-1-0-release/

Categories