javabytebuffer

Remove first n bytes from a ByteBuffer


How can I remove the first n number of bytes from a ByteBuffer without changing or lowering the capacity? The result should be that the 0th byte is the n+1 byte. Is there a better data type in Java to do this type of action?


Solution

  • You could try something like this:

    public void removeBytesFromStart(ByteBuffer bf, int n) {
        int index = 0;
        for(int i = n; i < bf.position(); i++) {
            bf.put(index++, bf.get(i));
            bf.put(i, (byte)0);
        }
        bf.position(index);
    }
    

    Or something like this:

    public void removeBytesFromStart2(ByteBuffer bf, int n) {
        int index = 0;
        for(int i = n; i < bf.limit(); i++) {
            bf.put(index++, bf.get(i));
            bf.put(i, (byte)0);
        }
        bf.position(bf.position()-n);
    }
    

    This uses the absolute get and put method of the ByteBuffer class and sets the position at next write position.

    Note that the absolute put method is optional, which means that a class that extends the abstract class ByteBuffer may not provide an implementation for it, for example it might throw a ReadOnlyBufferException.

    Whether you choose to loop till position or till limit depends on how you use the buffer, for example if you manually set the position you might want to use loop till limit. If you do not then looping till position is enough and more efficient.

    Here is some testings:

    @Test
    public void removeBytesFromStart() {
        ByteBuffer bf = ByteBuffer.allocate(16);
        int expectedCapacity = bf.capacity();
        bf.put("abcdefg".getBytes());
    
        ByteBuffer expected = ByteBuffer.allocate(16);
        expected.put("defg".getBytes());
    
        removeBytesFromStart(bf, 3);
    
        Assert.assertEquals(expectedCapacity, bf.capacity());
        Assert.assertEquals(0, bf.compareTo(expected));
    }
    
    @Test
    public void removeBytesFromStartInt() {
        ByteBuffer bf = ByteBuffer.allocate(16);
        int expectedCapacity = bf.capacity();
        bf.putInt(1);
        bf.putInt(2);
        bf.putInt(3);
        bf.putInt(4);
    
        ByteBuffer expected = ByteBuffer.allocate(16);
        expected.putInt(2);
        expected.putInt(3);
        expected.putInt(4);
    
        removeBytesFromStart2(bf, 4);
    
        Assert.assertEquals(expectedCapacity, bf.capacity());
        Assert.assertEquals(0, bf.compareTo(expected));
    }