Java: Convert byte to integer - java

I need to convert 2 byte array ( byte[2] ) to integer value in java. How can I do that?

You can use ByteBuffer for this:
ByteBuffer buffer = ByteBuffer.wrap(myArray);
buffer.order(ByteOrder.LITTLE_ENDIAN); // if you want little-endian
int result = buffer.getShort();
See also Convert 4 bytes to int.

In Java, Bytes are signed, which means a byte's value can be negative, and when that happens, #MattBall's original solution won't work.
For example, if the binary form of the bytes array are like this:
1000 1101 1000 1101
then myArray[0] is 1000 1101 and myArray[1] is 1000 1101, the decimal value of byte 1000 1101 is -115 instead of 141(= 2^7 + 2^3 + 2^2 + 2^0)
if we use
int result = (myArray[0] << 8) + myArray[1]
the value would be -16191 which is WRONG.
The reason why its wrong is that when we interpret a 2-byte array into integer, all the bytes are
unsigned, so when translating, we should map the signed bytes to unsigned integer:
((myArray[0] & 0xff) << 8) + (myArray[1] & 0xff)
the result is 36237, use a calculator or ByteBuffer to check if its correct(I have done it, and yes, it's correct).

Well, each byte is an integer in the range -128..127, so you need a way to map a pair of integers to a single integer. There are many ways of doing that, depending on what you have encoded in the pair of bytes. The most common will be storing a 16-bit signed integer as a pair of bytes. Converting that back to an integer depends on whether you store it big-endian form:
(byte_array[0]<<8) + (byte_array[1] & 0xff)
or little endian:
(byte_array[1]<<8) + (byte_array[0] & 0xff)

Also, if you can use the Guava library:
Ints.fromByteArray(0, 0, myArray[1], myArray[0]);
It was worth mentioning since a lot of projects use it anyway.

Simply do this:
return new BigInteger(byte[] yourByteArray).intValue();
Works great on Bluetooth command conversions etc. No need to worry about signed vs. unsigned conversion.

import java.io.*;
public class ByteArray {
public static void main(String[] args) throws IOException {
File f=new File("c:/users/sample.txt");
byte[]b={1,2,3,4,5};
ByteArrayInputStream is=new ByteArrayInputStream(b);
int i;
while((i=is.read())!=-1) {
System.out.println((int)i);
FileOutputStream f1=new FileOutputStream(f);
FileOutputStream f2=new FileOutputStream(f);
ByteArrayOutputStream b1=new ByteArrayOutputStream();
b1.write(6545);
b1.writeTo(f1);
b1.writeTo(f2);
b1.close();
}

Related

binary value comes wrong after & with 0x000000FF [duplicate]

I'm reading a file into a byte array in chunks and sending it over the network via a POST request to a webserver. It's not anything complicated, I've done it before using this exact same code. This time, I noticed that my images are looking really odd when they get to the server, so I decided to look at the byte array being sent and the one being received just to make sure it was the same. It's not. On the java sending side the byte array contains negative numbers. On the C# receiving side, there are no negative numbers.
The first 15 bytes on the receiving side (C#)
137
80
78
71
13
10
26
10
0
0
0
13
73
72
68
Those same bytes but on the sending side (java)
-119
80
78
71
13
10
26
10
0
0
0
13
73
72
68
All of the non-negative numbers are the same, and the -119 isn't the only negative number, they are all over. I did notice that -119 and 137 are 256 apart and wondered if that has something to do with it.
The code I'm using to read the image (java)
public static byte[] readPart(String fileName, long offset, int length) throws FileNotFoundException, Exception
{
byte[] data = new byte[length];
File file = new File(fileName);
InputStream is = new FileInputStream(file);
is.skip(offset);
is.read(data,0,data.length);
is.close();
return data;
}
The code I'm using to write the data (c#)
private void writeFile(string fileName, Stream contents)
{
using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = contents.Read(buffer, 0, bufferLen)) > 0)
{
fs.Write(buffer, 0, count);
}
fs.Close();
}
contents.Close();
}
I don't know if that is something that always happens and I just never noticed it before or if it is something that decided to go horribly wrong. What I do know is that this code worked before for something very similar and that it's not working now.
If anyone has any suggestions or an explanation I would really appreciate it.
EDIT:
The reason my images were looking odd is how I was calling the readPart method.
byte[] data = FileUtilities.readPart(fileName,counter,maxFileSize);//counter is the current chunk number
How I should have been calling it
byte[] data = FileUtilities.readPart(fileName,counter*maxFileSize,maxFileSize);//the current chunk * cuhnksize for the offset...
Thanks everyone, I'm significantly less confused now :)
In Java, byte is a signed value (using two's complement to encode negative values), so what you see it correct if unexpected by most people.
To convert a byte to an unsigned int value, use b & 0xff
Java doesn't have unsigned bytes; all bytes are treated as signed. That's all.
All that really matters is how you think of the bytes, since you rarely ever actually need to do comparisons on bytes. The only significant difference is that they print out as signed, as you've discovered.
If you like, you can use e.g. Guava's UnsignedBytes utilities to view Java bytes as unsigned, but there's really not much practical difference.
As a further explanation, assume you have 137 as an unsigned byte. That is represented as:
1000 1001
This binary value, when expressed as a signed two's complement number, turns out to be -119. (-128 + 9)
Any unsigned byte values over 128 will be affected by the difference since the left-most bit is used in this way by the two's complement scheme.
Maybe it has something to do with the fact that Java's byte is signed (range -128 to 127) while C#'s is unsigned (0 to 255) :). The information is the same in binary, it's just interpreted differently.
The range of byte is from -128 to 127, so if you try to assign a byte 128, it will cycle around and the result will be -128.
System.out.println("Max val = " + Byte.MAX_VALUE); //prints: Max val = 127
System.out.println("Min val = " + Byte.MIN_VALUE); //prints: Min val = -128
System.out.println("(byte)137 = " + (byte)137); //prints: (byte)137 = -119
System.out.println("(byte)128 = " + (byte)128); //prints: (byte)128 = -128
System.out.println("(byte)-129 = " + (byte)-129); //prints: (byte)-129 = 127

consolidating bytes in java

As part of a program I'm writing I need to consolidate two bytes into a long from an array of bytes.
So assuming this:
byte a[] = new byte[2]
a[0] = 0b1000111
a[1] = 0b1111000
how can I consolidate them such that
long b = 0b10001111111000
EDIT: The program will attempt to consolidate anywhere between 2 bytes and 100, just for reference.
java.nio can do that:
ByteBuffer.wrap(a).getShort()
BigInteger can do this: http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html
BigInteger buffer = new BigInteger(yourByteArray);
long result = buffer.longValue();
Note that if your byte array has a value larger than a long (eg, you mentioned that you might go up to 100 bytes), toLong() will only return the value of the lower value bytes. BigInteger, however, will handle any arbitrary number of bytes.
In order to combine those two bytes you will only need 16 bits. A short will suffice:
short result = (short)(((a[0] & 0xff) << 8) | (a[1] & 0xff))
If for some reason, you need the long data type, you need only replace the cast with a long.

Long to Byte Conversion

I have written the following program in Java to convert long to byte.
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a & 0xff);
System.out.println("the value of b is" +b);
}
}
The problem is I get the result -34 for the variable b.
Please tell me how to get the correct value. I want the value in bytes only.
Java's types are signed, bytes allow numbers between −128 and +127.this is the reason you were getting −34 for 222 value
long a=121;
byte b=(byte)(a );
System.out.println("the value of b is" +b);
All integer types (including byte) are signed in Java, so if you stick 222 into a Java byte you get an overflow (resulting in the negative number you saw). If you need the range 0–255 for a integral number in Java you'll need at least a short.
However, if you're just going to write that result somewhere as a single byte you don't need to worry, as its bit pattern representation is exactly the same as 222 in an unsigned byte.
You can use the java.lang.Long class' byteValue() method:
byte b = a.byteValue();
You will have to make a Long type object as such:
Long a = new Long(222);
And as others have noted, this will return -34 due to overflow of the range that can be represented by a byte which is 8 bits.
When you print a byte it assumes a range of -128 to 127.
If you print
byte b = (byte) 222;
you should expect to get a negative number.
If you want to store the range 0 to 255 you need to convert it when you get the value out.
int i = 222;
byte[] b = { (byte) i };
int i2 = b[0] & 0xFF; // give me the original unsigned 0 to 255.
assert i == i2;
You can invent all sorts of encoding. e.g. Say you want to store numbers which are only in millions say 0 to 200 million or decimal numbers -1.00 to 1.00 in a byte. You might first think this is impossible because a byte only stores 8 bits.
// store millions.
byte b = (byte) (i / 1000000);
int i = (b & 0xff) * 1000000;
// store decimal from -1.00 to 1.00
byte b = (byte) Math.round(d * 100);
double d = b / 100.0;
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a);
System.out.println("the value of b is" +b);
}
}
This byte bValue = (byte) num; statement is converted into a byte format.

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));
}

Java: Bytes to floats / ints

I have a byte array sent via UDP from x-plane. The bytes (4) are all floats or integers…
I tried to cast them to floats but no luck so far…
Example array:
byte data[41] = {-66,30,73,0};
How do I convert 4 bytes into int or float and doesn't float use 8 bytes?
Note: I recommend #Ophidian's ByteBuffer approach below, it's much cleaner than this. However this answer can be helpful in understanding the bit arithmetic going on.
I don't know the endianness of your data. You basically need to get the bytes into an int type depending on the order of the bytes, e.g.:
int asInt = (bytes[0] & 0xFF)
| ((bytes[1] & 0xFF) << 8)
| ((bytes[2] & 0xFF) << 16)
| ((bytes[3] & 0xFF) << 24);
Then you can transform to a float using this:
float asFloat = Float.intBitsToFloat(asInt);
This is basically what DataInputStream does under the covers, but it assumes your bytes are in a certain order.
Edit - On Bitwise OR
The OP asked for clarification on what bitwise OR does in this case. While this is a larger topic that might be better researched independently, I'll give a quick brief. Or (|) is a bitwise operator whose result is the set of bits by individually or-ing each bit from the two operands.
E.g. (in binary)
10100000
| 10001100
-----------
10101100
When I suggest using it above, it involves shifting each byte into a unique position in the int. So if you had the bytes {0x01, 0x02, 0x03, 0x04}, which in binary is {00000001, 00000010, 00000011, 00000100}, you have this:
0000 0001 (1)
0000 0010 (2 << 8)
0000 0011 (3 << 16)
| 0000 0100 (4 << 24)
--------------------------------------------------------
0000 0100 0000 0011 0000 0010 0000 0001 (67 305 985)
When you OR two numbers together and you know that no two corresponding bits are set in both (as is the case here), bitwise OR is the same as addition.
See Also
Wikipedia: Bitwise OR
You probably want to make use of java.nio.ByteBuffer. It has a lot of handy methods for pulling different types out of a byte array and should also handle most issues of endianness for you (including switching the byte order if necessary).
byte[] data = new byte[36];
//... populate byte array...
ByteBuffer buffer = ByteBuffer.wrap(data);
int first = buffer.getInt();
float second = buffer.getFloat();
It also has fancy features for converting your byte array to an int array (via an IntBuffer from the asIntBuffer() method) or float array (via a FloatBuffer from the asFloatBuffer() method) if you know that the input is really all of one type.
Use a DataInputStream as follows:
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
float f = dis.readFloat();
//or if it's an int:
int i = dis.readInt();
You cannot just cast them into a float/int. You have to convert the bytes into an int or float.
Here is one simple way to do it:
byte [] data = new byte[] {1,2,3,4};
ByteBuffer b = ByteBuffer.wrap(data);
System.out.println(b.getInt());
System.out.println(b.getFloat());
There is a reasonable discussion here:
http://www.velocityreviews.com/forums/t129791-convert-a-byte-array-to-a-float.html
In my opinion the ByteBuffer approach is better, you can specify where the data is wrapped (from which byte index, here 0) and also the endianness (here BIG_ENDIAN).
try {
float result = ByteBuffer.wrap(data, 0, 4).order(BIG_ENDIAN).getFloat();
} catch (IndexOutOfBoundsException exception) {
// TODO: handle exception
}
Functions similar to getFloat() exist for Int, Short, Long...

Categories