views:

1328

answers:

3

Hi,

since Java doesn't provide a default way to do this,

what's a fast way to convert an Integer into a Byte Array?

e.g. 0xAABBCCDD => {AA, BB, CC, DD}

+11  A: 

Have a look at the ByteBuffer class.

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

Setting the byte order ensures that result[0] == 0xAA, result[1] == 0xBB, result[2] == 0xCC and result[3] == 0xDD.

Or alternatively, you could do it manually:

byte[] toBytes(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;
}

The ByteBuffer class was designed for such dirty hands tasks though. In fact the private java.nio.Bits defines these helper methods that are used by ByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }
Gregory Pakosz
this would work well if the bytebuffer is already there... otherwise it seems like it would take longer to do the allocation, than to just allocate a byte array of length 4 and do the shifting manually... but we're probably talking about small differences.
Jason S
get it right first, then profile, then optimize ;)
Gregory Pakosz
The ByteBuffer instance can be cached; and internally it's surely implemented with shifting and masking anyway.
Gregory Pakosz
This is a perfectly fine answer. Note that big-endian is the specified default, and the methods are "chainable", and the position argument is optional, so it all reduces to:byte[] result = ByteBuffer.allocate(4).putInt(0xAABBCCDD).array();Of course, if you're doing this repeatedly and concatenating all the results together (which is common when you're doing this kind of thing), allocate a single buffer and repeatedly putFoo() all the things into it that you need -- it will keep track of the offset as you go. It's really a tremendously useful class.
Kevin Bourrillion
@Kevin, thank you
Gregory Pakosz
+2  A: 

You can use BigInteger:

From Integers:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

The returned array is of the size that is needed to represent the number, so it could be of size 1, to represent 1 for example. However, the size cannot be more than four bytes if an int is passed.

From Strings:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

However, you will need to watch out, if the first byte is higher 0x7F (as is in this case), where BigInteger would insert a 0x00 byte to the beginning of the array. This is needed to distinguish between positive and negative values.

notnoop
thanks!But since this is BigInteger, will ints wrap around correctly? That is integers that are outside Integer.MAX_VALUE but can still be represented with only 4 bytes?
Buttercup
This is certainly not fast to execute. ;)
Peter Lawrey
This is not a good option. Not only it may add 0x00 byte, it may also strip leading zeros.
ZZ Coder
+2  A: 

Using BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

Using DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {   
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

Using ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}
Pascal Thivent
pay attention to the byte order though
Gregory Pakosz