57

I'm trying to slice a byte array to prune the first part of the array. I'm using ByteBuffer but it does not behave like I would expect.

byte[] myArray = new byte[10];
ByteBuffer buf = ByteBuffer.wrap(myArray);
buf.position(5);
ByteBuffer slicedBuf = buf.slice();
byte[] newArray = slicedBuf.array();

I would expect the size of newArray to be 5, containing only the last portion of my ByteBuffer. Instead, the full byte array is returned. I understand that this is because the "backing buffer" is the same all along.

How can I slice to have only the desired part of the array?

EDIT: Added context

The bytes are received from network. The buffer is formed like this :

[ SHA1 hash ] [ data... lots of it ]

I already have a function that takes a byte array as a parameter and calculate the SHA1 hash. What I want is to slice the full buffer to pass only the data without the expected hash.

1
  • If you didn't write the hashing function you're kinda stuck once you have everything in one byte[] if you want to avoid a copy. Why not read the hash from the network into one array and the data into another? Commented Aug 21, 2013 at 21:42

3 Answers 3

136

You can use the Arrays.copyOfRange method. For example:

// slice from index 5 to index 9
byte[] slice = Arrays.copyOfRange(myArray, 5, 10);
4
  • 10
    Thank you for your answer. Do you know if there is any way to do this without copying? My array can reach many megabytes so I would prefer to avoid copying if possible
    – Eric
    Commented Aug 21, 2013 at 21:31
  • 1
    The bytes in byte arrays cannot be reused by different arrays. You have the ByteBuffer class for this purpose. Alternatively, change your SHA1 function so that it accepts the offset and length for a slice in addition to the array.
    – Joni
    Commented Aug 21, 2013 at 21:39
  • I don't think I can change my hash algo since it is javax.crypto.mac. I have no control on parameters passed to it.
    – Eric
    Commented Aug 21, 2013 at 21:43
  • 4
    Use the update(byte[],int,int) method (docs.oracle.com/javase/7/docs/api/javax/crypto/…)
    – Joni
    Commented Aug 21, 2013 at 21:48
9

The ByteBuffer you created is being backed by that array. When you call slice() you effectively receive a specific view of that data:

Creates a new byte buffer whose content is a shared subsequence of this buffer's content.

So calling array() on that returned ByteBuffer returns the backing array in its entirety.

To extract all the bytes from that view, you could do:

byte[] bytes = new byte[slicedBuf.remaining()];
slicedBuf.read(bytes);

The bytes from that view would be copied to the new array.

Edit to add from comments below: It's worth noting that if all you're interested in doing is copying bytes from one byte[] to another byte[], there's no reason to use a ByteBuffer; simply copy the bytes.

4
  • Basically, if the word ByteBuffer exists in your answer, it's a bad answer. See Joni's answer for the bast (and only acceptable IMHO) answer.
    – Bohemian
    Commented Aug 21, 2013 at 21:17
  • 7
    I answered the OP's question, not an interpretation of his intent. In addition, If your answer doesn't have any content explaining the why things work, it's a bad answer. Commented Aug 21, 2013 at 21:19
  • Yes, thank you for your answer. I am porting code from C and I don't have any copying there, only pointer manipulation so I was expecting something alike in Java. My array can reach many megabytes so copying is pretty wasteful
    – Eric
    Commented Aug 21, 2013 at 21:30
  • 1
    @Eric - Yeah, Java is ... different. If you trying to avoid the copy I'd need more context on what the bytes represent and what you're trying to do with them. Commented Aug 21, 2013 at 21:33
0

a more modern approach System.arraycopy

srcBuffer – the source array
srcPos – starting position in the source array
destBuffer – the destination array
destPos – starting position in the destination data
length – the number of array elements to be copied


System.arraycopy(srcBuffer, srcPos, destBuffer, destPos, length);
1

Not the answer you're looking for? Browse other questions tagged or ask your own question.