Java 从 ByteBuffer 中删除前 n 个字节

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18031927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:54:38  来源:igfitidea点击:

Remove first n bytes from a ByteBuffer

javabytebuffer

提问by Blaker

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

如何在不更改或降低容量的情况下从 ByteBuffer 中删除前n个字节?结果应该是第0个字节是n+1个字节。Java 中是否有更好的数据类型来执行此类操作?

采纳答案by A4L

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 getand putmethod of the ByteBufferclass and sets the positionat next write position.

本品采用绝对GET看跌期权的方法的ByteBuffer类和设置位置在下次写位置。

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

请注意,absoluteput方法是可选的,这意味着扩展抽象类的类ByteBuffer可能不会为其提供实现,例如它可能会抛出ReadOnlyBufferException.

Whether you choose to loop till positionor till limitdepends on how you use the buffer, for example if you manually set the positionyou might want to use loop till limit. If you do not then looping till positionis enough and more efficient.

无论您选择循环直到位置或至极限取决于你如何使用缓冲,例如,如果您手动设置的位置,你可能要使用循环至limit。如果你不这样做,那么循环直到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));
}

回答by andreih

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

回答by PeterErnsthaft

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() 处的字节被复制到索引 0,索引 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

回答by Serhiy Brytskyy

Use compact method for that. E.g.:

为此使用紧凑方法。例如:

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