Converting an unsigned byte array to an integer

November 29, 2004
java

I found myself today needing to deal with unsigned integers, and shorts in java. In Java there is no unsigned keyword like in C, or other languages. All primitives are signed (meaning they can hold negative values).

So I came up with two functions for converting the unsigned byte arrays into numbers I can use (thanks to Matt Finn, here at ActivSoftware for some pointers). I am posting these to help others, and to see if anyone knows of a more efficient or easier way to do this:

/**
 * Converts a 4 byte array of unsigned bytes to an long
 * @param b an array of 4 unsigned bytes
 * @return a long representing the unsigned int
 */
public static final long unsignedIntToLong(byte[] b) 
{
    long l = 0;
    l |= b[0] & 0xFF;
    l <<= 8;
    l |= b[1] & 0xFF;
    l <<= 8;
    l |= b[2] & 0xFF;
    l <<= 8;
    l |= b[3] & 0xFF;
    return l;
}
    
/**
 * Converts a two byte array to an integer
 * @param b a byte array of length 2
 * @return an int representing the unsigned short
 */
public static final int unsignedShortToInt(byte[] b) 
{
    int i = 0;
    i |= b[0] & 0xFF;
    i <<= 8;
    i |= b[1] & 0xFF;
    return i;
}

You will notice that the functions actually return a long for unsinged integers, and an integer for shorts, this is because we can't store a large unsigned int in a java int. You may also be interested to know that byte's, short's, and int's are all actually stored using 4 bytes by the jvm (so they can perform 32 bit operations).



Related Entries

13 people found this page useful, what do you think?

Comments

You can use my BinaryTools class freely, at http://cvs.sourceforge.net/viewcvs.py/joustim/joscar/src/net/kano/joscar/BinaryTools.java?view=markup It provides methods for dealing with binary data, including two methods very similar to the two you posted. It uses my ByteBlock class, but you could easily change it (using IDEA's structural search & replace for example) to use byte arrays.
if you want it to run at least 8 times slower you can wrap the byte array in a java.nio.ByteBuffer and use its getInt method
You could try doing it like this. It is basically the same, but much faster. For the unsignedShortToInt, it is about 1/3 faster, where unsignedIntToLong is five times faster. <pre> public static final long unsignedIntToLong(byte[] b) { return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; } public static final int unsignedShortToInt(byte[] b) { return (b[0] << 8) | b[1]; } </pre>
Shortest version would be (masking to 0xff is necessary): return ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16) | ((b[2] & 0xFF) << 8) | b[3] & 0xFF; You can probably can do some bytecode tweaking to make it bit shorter but not necessary faster.
Good work dude !!! Thanks I needed it.
This code converts directly from an int to a long. int i = ...; long l = i < 0 ? 0x0000000100000000L + i : i;
on my pc (J2SE V1.4.2_04), I have to cast to a long before each operation: return ((long)(b[0] & 0xFF) << 24) | ((long)(b[1] & 0xFF) << 16) | ((long)(b[2] & 0xFF) << 8) | (long)b[3] & 0xFF;
Exactly what I was looking for, thanks!
Thanks guys, just what I was looking for!
A probably slower but more flexible way is: int i = new BigInteger(1,bytes).intValue(); which takes any length array. Especially handy for doing IP filtering for both IPv4 and IPv6
Very useful, thank you
thanx... i wasnt '&' it with FF. my code worked because i never tested with values which would give me a -ve int. but looking at this i realized that it had a bug and it sometimes might not work without the '& 0xFF'
Just another alternative for converting directly from an int (treated as unsigned) to a long: int i = ...; long res = (i & 0x7FFFFFFF) + ((long)(i>>>31)<<31); Hope someone (other than me!) finds that helpful
// Just an observation ... // The value of uiLong1 after the bit // shifts will be the C++ unsigned int // equivalent of -9999 long uiLong1 = -9999; uiLong1 <<= 32; uiLong1 >>>= 32;
i'm getting 145 in first byte, tht means 8th bit will be on, when it reaches after shifting on 32th bit, if cozez the signed bit to on, which changes the value...wht'll be the solutiion...thnx in adv
And how about value & 0xffffffffL????
As for casting an unsigned short to an int, this is even easier i you have the short to start with: (int)(char)ushort Why does this work? char is the only unsigned numeric primitive in Java.
There is a difference in little endian and big endian byte order. I had to exchange b[0] and b[1] to get little endian with unsignedShortToInt.
18-year career of former SmackDown Superstar, Undertaker.- Ric Flair, Scott Steiner, Rick Steiner, Jeff Jarrett, Lex Luger, Buff Bagwell,John Cena , Undertaker,Goldberg & Hulk Hogan & Sting vs. Kevin Nash & Sid Vicious . http://www.salazarfill.com/wrestling.htm ????????-?????? ???.
There's a much easier way to do it: to byte array - BigInteger.valueOf(num).toByteArray() from byte array - new BigInteger(array).intValue()
Since java version 1.4, use of ByteBuffer makes these conversions easier, keeping the details of the conversion obfuscated. Unfortunately, when reading binary data files one must either know or be able to detect byte ordering, i.e. little/bin endian, for proper conversion. For example; import java.nio.ByteBuffer; public class tt { static public void main(String[] args) throws Exception { byte[] buffer = new byte[55]; // Initialize a network byte order int to 1234 buffer[2] = (byte)0x04; buffer[3] = (byte)0xD2; // Use ByteBuffer.getInt() to "convert" the byte[] to int int ival = ByteBuffer.wrap(buffer).getInt(); // Print out the value System.out.println("length is " + ival); } // public static void main(String[] args) } // public class tt
You can use java.nio.ByteBuffer of you want to convert an array of bytes into a stream of integers. ByteBuffer keyBuffer = ByteBuffer.wrap(rowByteArray); try { int nextInt = keyBuffer.getInt(); // do operations on the integer here } catch(BufferUnderflowException e) { // handle the last 3 bytes }
DUDE .. You saved my day. I am beginner in C C++ and was kind of hit the wall. You saved my night :)



Thanks Alot
WHY TO WORRY GUYS..

1.FIRST CONVERT THE BYTE ARRAY TO STING.

2.THEN CONVERT THE STRING TO INTEGER.

EXAMPLE:

byte[] MyByteArray;

String Str = new
String(MyByteArray);

int Value = Integer.parseInt(Str);

Enjoy :)
Very nice "unsignedShortToInt" method.
Thanks a million, spent a day or so trying to figure this out!
Hi Pete,

I spent some time this weekend wrapping my head around what you're doing here. Nice work! It was a great mental exercise. :)

Take care,
-Aaron
I had a co-worker recommend using

int i = (int) ByteBuffer.wrap(bytes).readShort()

This ByteBuffer doesn't work because the java short is signed and you loss the ability to store a value over 127. For example, the byte (0x80) is converted to a short = -128 instead of what we would want +128. The only way to make this work with a ByteBuffer is to use getInt() and pad the bytearray with two 0x00 bytes. But I think the binary manipulation is more efficient.

Post a Comment




  



Spell Checker by Foundeo

Recent Entries



foundeo


did you hack my cf?