58

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

137

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

// slice from index 5 to index 9
byte[] slice = Arrays.copyOfRange(myArray, 5, 10);
Sign up to request clarification or add additional context in comments.

4 Comments

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
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.
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.
Use the update(byte[],int,int) method (docs.oracle.com/javase/7/docs/api/javax/crypto/…)
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 Comments

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.
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.
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 - 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.
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 Comment

Why is this a "more modern" approach? This method was already present in JDK1.0 (javaalmanac.io/jdk/1.0/api/java.lang.System.html). Arrays.copyOfRange of the accepted answer in JDK1.6.

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.