Getting the wrong number when converting from byte[] to int - java

I am trying to convert an int to a byte[] and back again, but I think I am doing something wrong along the way. My code is basically:
byte[] array = new byte[4];
array[3] = (byte) ( num & 0xFF);
array[2] = (byte) ((num >> 8) & 0xFF);
array[1] = (byte) ((num >> 16) & 0xFF);
array[0] = (byte) ((num >> 24) & 0xFF);
And:
for (int i =0; i < 4; i++) {
num = (num << 8) + (array[i] & 0xff);
}
If I start off with the number 72, for example, after converting it to a byte array and back I get the number 795108710. Am I missing a step, or are maybe my endians mixed up? Thanks for your time.

Use a ByteBuffer; it contains methods to encode many different data types without the need to worry about endian and the like:
ByteBuffer bb = ByteBuffer.allocate(32);
bb.putInt(index, 72);
...
int value = bb.getInt(index);

Try this:
array[3]=(byte)(num & 0xFF);
array[2]=(byte)(num & 0x0000FF00);
array[1]=(byte)(num & 0x00FF0000);
array[0]=(byte)(num & 0xFF000000);
To get it back:
num=(int)(array[0]&0xFF) | (int)(array[1]&0xFF) | (int)(array[2]&0xFF) | (int)(array[3]&0xFF);
Or try a loop if you want:
for(int i=0; i<4; i++)
{
num=num+(int)(array[i]&0xFF);
}
This one is in C#. Not sure if it would work on Java. But I think, will do.

Related

how to convert long to byte array in java? [duplicate]

This question already has answers here:
How do I convert Long to byte[] and back in java
(18 answers)
Closed 6 years ago.
I have made long value from byte array using this code
byte[] by = {07, 53 -70, 74};
long value = 0;
for (int i = 0; i < by.length; i++) {
value = ((value << 8) + (by[i] & 0xff));
}
System.out.println(value);
out put is 520010
now I want reverse process on this and I tried it this way
long ts = 520010;
tm_stp[0] = (byte) ((byte) ts>>24);
tm_stp[1] = (byte) ((byte) ts>>16);
tm_stp[2] = (byte) ((byte) ts>>8);
tm_stp[3] = (byte) ts;
for (byte b : tm_stp) {
System.out.println(b);
}
and output is 0 0 0 74
what is wrong in my second part of code please help me, Thanks!
The problem is the fact that you cast to byte too early:
tm_stp[0] = (byte) ((byte) ts>>24);
tm_stp[1] = (byte) ((byte) ts>>16);
tm_stp[2] = (byte) ((byte) ts>>8);
//^^^^
This causes the ts value to be truncated, replacing the first 24 bytes with 0s. After that, shifting by anything greater than or equal to 8 will return 0. To avoid incorrect behaviour with negative values, you should also use a bitmask. The correct code should look like this:
tm_stp[0] = (byte) ((ts >> 24) & 0xFF);
tm_stp[1] = (byte) ((ts >> 16) & 0xFF);
tm_stp[2] = (byte) ((ts >> 8) & 0xFF);
tm_stp[3] = (byte) ((ts >> 0) & 0xFF); // >> 0 not actually required, only for symmetry
Don't convert ts to byte before shifting.
tm_stp[0] = (byte) (ts >> 24);
tm_stp[1] = (byte) (ts >> 16);
tm_stp[2] = (byte) (ts >> 8);
tm_stp[3] = (byte) ts;

Convert 3 bytes array to number

I convert a short number to a 3 byte array using the following code:
static byte[] convertTo3ByteArray(short s) {
byte[] ret = new byte[3];
ret[0] = (byte) (s & 0xff);
ret[1] = (byte) ((s >> 8) & 0xff);
ret[2] = (byte) (0x00);
return ret;
}
This works very well.
I found a code on Stackoverflow to convert the array back to a number:
static int convertToInt(byte[] b) {
return ((b[0] << 0) | (b[1] << 8) | (b[2] << 16));
}
And when I convert 258 to byte array, and then use this code, it returns 258.
But for number 675, this code returns -93.
How do I have to change the convertToShort method to get 675 back?
I suppose it has something to do with bitshift and loss of data? Or signed bytes?
Try with this modified method:
static int convertToShort(byte[] b) {
return (((b[0] & 0xFF) << 0) | ((b[1] & 0xFF) << 8) | ((b[2] & 0xFF) << 16));
}
In the array some bytes are negative, you need to convert them back to "positive values" with byteVal & 0xFF before doing the bit shift
A short has 16 bits of information, so that would be two bytes. When you try to store a third byte with | (b[2] << 16), it would go off the end of the short's bits, which is a problem. I.e. you can't do what you want to.
Changing to using a char datatype will fix this issue as they are the only unsigned type in Java:
https://stackoverflow.com/a/21089624/1590490
static char[] convertTo3ByteArray(short s) {
char[] ret = new char[3];
ret[0] = (char) (s & 0xff);
ret[1] = (char) ((s >> 8) & 0xff);
ret[2] = (char) (0x00);
return ret;
}
static int convertToShort(char[] b) {
return ((b[0]) | (b[1] << 8) | (b[2] << 16)); // the original << 0 shift does nothing
}

Byte to integer

I am trying to convert a byte to integer. All the searches I have done use byte[] which I assume is any array. I want to convert F byte (not b as show below) but it gives error to change: not applicable to the argument.
byte F;
mmInStream.read(packetBytes);
b [counter]= packetBytes[0];
F=b [counter];
counter++;
temp = byteToInt(b); //Convert byte to int
Here is a byte To Int I found on one of the sites.
private int byteToInt(byte[] b) {
int value= 0;
for(int i=0;i<b.length;i++){
int n=(b[i]<0?(int)b[i]+256:(int)b[i])<<(8*i);
value+=n;
}
return value;
}
Simply do:
byte b = ...;
int signedInt = b; // For negative bytes, resulting in negative ints
int unsignedInt = 0xFF & b; // For negative bytes, resulting in positive ints
FYI: An int is 4 bytes. So, that is the reason why the methods you found on the internet are using an array of bytes. They assume you pass an array of 4 bytes, which will be stitched together to make an int.
you can use this:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
or this one also:
public static byte[] intToByteArray(int a)
{
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
and
public static int byteArrayToInt(byte[] b)
{
return (b[3] & 0xFF) + ((b[2] & 0xFF) << 8) + ((b[1] & 0xFF) << 16) + ((b[0] & 0xFF) << 24);
}
if b is unsigned
int i = b & 0xff;

Converting int to byte in Android

Actually I need to transfer the integer value along with the bitmap via bluetooth.. Now my problem is I need to transfer the integer as single byte value..
Is tat possible to convert int as single byte value.. and retrieve it as a integer there... I tried byteValue() and the casting thing but its not usefull.. If my approach is right just help me out with this or say some other way.
(Each time when I am using casting then it's returning as 65535)
What about this?
public static byte[] intToByteArray(int a)
{
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
and
public static int byteArrayToInt(byte[] b)
{
return (b[3] & 0xFF) + ((b[2] & 0xFF) << 8) + ((b[1] & 0xFF) << 16) + ((b[0] & 0xFF) << 24);
}
If you're completely sure, that your int variable contains a byte value [-128; 127] then it should be as simple as:
int i = 100; // your int variable
byte b = (byte) i;
A single byte (8 bits) can only contain 2^8 unsigned integers, i.e [0, 255]. For signed you loose the first bit and the range becomes [-128, 127]. If your integer fits then a simple cast should work.
for 0-255 numbers.
int i = 200; // your int variable
byte b = (byte)(i & 0xFF);

Convert short to byte[] in Java

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.
ret[0] = (byte)(x & 0xff);
ret[1] = (byte)((x >> 8) & 0xff);
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.
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;
Figured it out, its:
public static byte[] toBytes(short s) {
return new byte[]{(byte)(s & 0x00FF),(byte)((s & 0xFF00)>>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())
}
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).
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;
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;
}
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]);

Categories

Resources