简体   繁体   English

从ByteBuffer中删除前n个字节

[英]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? 如何在不更改或降低容量的情况下从ByteBuffer中删除前n个字节? The result should be that the 0th byte is the n+1 byte. 结果应该是第0个字节是n + 1个字节。 Is there a better data type in Java to do this type of action? Java中是否有更好的数据类型可以执行此类操作?

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. 这使用ByteBuffer类的绝对getput方法,并将位置设置在下一个写入位置。

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 . 请注意,绝对put方法是可选的,这意味着扩展抽象类ByteBuffer的类可能无法为其提供实现,例如,它可能抛出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 . 是否选择循环直到位置或直到极限取决于缓冲区的使用方式,例如,如果手动设置位置 ,则可能要使用循环直到limit If you do not then looping till position is enough and more efficient. 如果不这样做,则循环直到position足够且更有效。

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));
}

I think the method you are looking for is the ByteBuffer's compact() method 我认为您正在寻找的方法是ByteBuffer的compact()方法

Even though the documentation says: 即使文档说:

"The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. That is, the byte at index p = position() is copied to index zero, the byte at index p + 1 is copied to index one, and so forth until the byte at index limit() - 1 is copied to index n = limit() - 1 - p. The buffer's position is then set to n+1 and its limit is set to its capacity." “将缓冲区当前位置与其限制之间的字节(如果有的话)复制到缓冲区的开头。也就是说,将索引p = position()处的字节复制到索引零,将索引p + 1处的字节复制为索引复制到索引1,依此类推,直到索引limit()-1处的字节复制到索引n = limit()-1-p。然后将缓冲区的位置设置为n + 1并将其限制设置为容量”。

I am not sure that this method realy does that, because when I debug it seems like the method just does buffer.limit = buffer.capacity . 我不确定该方法是否确实能够做到这一点,因为在调试时,似乎该方法只是执行buffer.limit = buffer.capacity

Do you mean to shift all the element to the begining of the buffer? 您的意思是将所有元素移到缓冲区的开头吗? Like this: 像这样:

    int n = 4;
    //allocate a buffer of capacity 10 
    ByteBuffer b = ByteBuffer.allocate(10); 

    // add data to buffer
    for (int i = 0; i < b.limit(); i++) {
        b.put((byte) i);
    }

    // print buffer
    for (int i = 0; i < b.limit(); i++) {
        System.out.print(b.get(i) + " ");
    }

    //shift left the elements from the buffer
    //add zeros to the end
    for (int i = n; i < b.limit() + n; i++) {
        if (i < b.limit()) {
            b.put(i - n, b.get(i));
        } else {
            b.put(i - n, (byte) 0);
        }
    }
    //print buffer again
    System.out.println();
    for (int i = 0; i < b.limit(); i++) {
        System.out.print(b.get(i) + " ");
    }

For n=4 it will print: 对于n = 4,它将打印:

0 1 2 3 4 5 6 7 8 9 
4 5 6 7 8 9 0 0 0 0

Use compact method for that. 为此使用紧凑的方法。 Eg: 例如:

    ByteBuffer b = ByteBuffer.allocate(32);
    b.put("hello,world".getBytes());
    b.position(6);      
    b.compact();
    System.out.println(new String(b.array()));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM