0

What's the best way to put an int at a certain point in a byte[] array?

Say you have a byte array:

byte[] bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int someInt = 12355; //0x43, 0x30

How can I do like bytes[4] = someInt; so that now bytes[4] will equal 0x43 and bytes[5] will be equal to 0x30?

I'm used to just using memcpy with C++ and don't know the alternatives in Java.

Thanks

2
  • 2
    possible duplicate of Java - Convert int to Byte Array of 4 Bytes? and a number of others ... Commented Dec 27, 2011 at 0:47
  • Actually, memcpy in C++ is not a portable solution because assumes that you want to copy the bytes into the array in the "natural" order of the platform ... Commented Dec 27, 2011 at 2:25

5 Answers 5

4

If you want also high 0-bytes of the int put into the byte[]:

void place(int num, byte[] store, int where){
    for(int i = 0; i < 4; ++i){
        store[where+i] = (byte)(num & 0xFF);
        num >>= 8;
    }
}

If you only want the bytes to the highest nonzero byte:

void place(int num, byte[] store, int where){
    while(num != 0){
        store[where++] = (byte)(num & 0xFF);
        num >>>= 8;
    }
}

If you want the bytes big-endian (highest byte at lowest index), the version storing all four bytes is very easy, the other one slightly more difficult:

void placeBigEndian(int num , byte[] store, int where){
    for(int i = 3; i >= 0; --i){
        store[where+i] = (byte)(num & 0xFF);
        num >>= 8;
    }
}

void placeBigEndian(int num, byte[] store, int where){
    in mask = 0xFF000000, shift = 24;
    while((mask & num) == 0){
        mask >>>= 8;
        shift -= 8;
    }
    while(shift > 0){
        store[where++] = (byte)((num & mask) >>> shift);
        mask >>>= 8;
        shift -= 8;
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

@Daniel Fischer: + 1, but same comment as the one I made to Martijn Courteaux's answer... The and (& 0xFF) is not necessary if you're converting to a (byte) anyway.
Yeah, it's not necessary, it just feels cleaner to explicitly mask the byte off. May be idiosyncratic.
Oops. I spotted a bug. You are putting the bytes in the wrong order in the array. Lowest bits should be at the right.
@Martijn I followed the example, where bytes[4] got the low byte and bytes[5] the higher. Nevertheless, added versions for the other order.
I see, but I think it is a mistake from the OP, because memcopy won't work like the OP showed in his example.
|
2

Note, you assume a big endian ordering! x86 is little endian... What's more, your int is 32bits long, hence 0x00004330 in big endian.

If this is what you want, use a ByteBuffer (which uses big endian ordering by default):

ByteBuffer buf = ByteBuffer.allocate(8);
// then use buf.putInt(yourint, index)
// buf.get(index) will read byte at index index, starting from 0

6 Comments

For primitive types?? That is a good way of slowing things down if that's the case!
And I can assert this is not the case when looking at JNI headers, where jint is a typedef for int
+1 for using an existing class (ByteBuffer) instead of writing your own code. Perhaps a better answer than my DataOutputStream proposal.
@EtiennedeMartel this is for class data, here I talk about primitive integer types at run time
@fge There's a second part in the accepted answer which talks about operands.
|
1

I don't see the problem, it looks like you solved it your own way:

public static void putShort(bytes[] array, int position, short value)
{
    byte leftByte = (byte) (value >>> 8);
    byte rightByte = (byte) (value & 0xFF);

    array[position] = leftByte;
    array[position + 1] = rightByte;
}

Note that an int is 4 bytes and a short is 2 bytes.

6 Comments

I'm not sure... How about negative numbers?
Even if the &0xFF isn't necessary, I've seen so many problems with sign extension I'd add it anyway. :-)
@MartijnCourteaux: (byte) (value & 0xFF) cannot give a different result than (byte) value. Paste an int for which (byte) (value & 0xFF) does give something else than (byte) value if you find one ; ) You're really saying "zero all bits besides the 8 lowest bits and then keep only the 8 lowest bits" versus directly "give me the lowest 8 bits". There's no point in zero'ing 24 bits that you're going to "discard" anyway : )
I wasn't sure because I know that the casting in Java for primitives isn't always that basic. Example: byte b = (byte) -1; Now b = 0xFF. And when you do afterwards: int i = b;. Now i = 0xFFFFFFFF, and not longer the original value of b which was 0xFF.
@Martijn Courteaux: it isn't called "casting", it's called converting : ) You're referring to a different type of conversion: "widening primitive conversion" (e.g. from byte to int). But when you're doing a "narrowing primitive conversion" (like from int to byte) then there's no issue because you're actually discarding all but the lowest bits : )
|
0

First of all, in Java you don't need to initialize byte arrays to zeroes. All arrays are initialized on construction time to 0/false/null.

Second, ints are signed 32-bit big-endian integers, so 12355 is actually 0x00003043. If you want to use 16-bit integers, use the short type.

Then, to get the individual bytes in your integer, you could do:

bytes[ i ]   = (byte) (someInt >> 24);
bytes[ i+1 ] = (byte) (someInt >> 16);
bytes[ i+2 ] = (byte) (someInt >> 8);
bytes[ i+3 ] = (byte) (someInt);

The conversion to byte truncates the remaining bits, so no & 0xFF mask is needed. I'm assuming i is the index of the array. To change the endianness, swap the offsets at the indices.

Comments

0

One approach would be to use a DataOutputStream and it's writeInt() method, wrapped around a ByteArrayOutputStream. e.g. (with no error-handling)

public byte[] writeIntAtPositionX(int position, int iVal) throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      DataOutputStream dos = new DataOutputStream(baos);

      // now, advancing to a specific spot is awkward.
      // presumably you are actually writing other stuff out before the integer
      // but if you really want to advance to a specific position

      for (int i = 0; i < position; i++)
         dos.writeByte(0);

      dos.writeInt(iVal);

      dos.flush();
      dos.close();
      return baos.toByteArray();  
   }

The big advantage of this method is that the guys who wrote Java figured out the byte ordering and the masking with 0xFF and all that stuff. Plus, if you ever envision writing doubles, shorts, longs or Strings etc. to your buffer you won't need to add all those methods, the work is already done.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.