ByteBuffer:写入,然后返回缓冲区的开头并在之前写入的所有数据之前写入(前置?)

时间:2012-06-18 00:34:19

标签: java nio bytebuffer prepend

使用 ByteBuffer 时,我仍然有些不稳定。我想要做的是将数据写入ByteBuffer,然后转到ByteBuffer的开头并在所有数据之前写入一个字节(写入数据包的有效负载,然后添加标题。)我该怎么办是什么?

图:

缓冲区以:

开头
|  PAYLOAD  |

添加操作码头之后的缓冲区(在我想做之后):

|  HEADER  |  PAYLOAD  |

|只是这类数据的分隔符,而不是任何数据。

3 个答案:

答案 0 :(得分:1)

您正在寻找的内容称为“分散 - 收集I / O”,ScatteringByteChannel.read(ByteBuffer[])GatheringByteChannel.write(ByteBuffer[])支持此功能。注意数组。 FileChannelSocketChannelDatagramSocketChannel以及管道渠道支持这些接口。

答案 1 :(得分:0)

ByteBuffer bbuf = ByteBuffer.allocate(HEADER_SZ + PAYLOAD_SZ);
bbuf.position(HEADER_SZ);
for(int i=0; i < PAYLOAD_SZ; i++)
    bbuf.put(payload[i]);
bbuf.rewind();
for(int i=0; i < HEADER_SZ; i++)
    bbuf.put(header[i]);

我已经对字节索引源数据做了假设。批量放置会更好,但这是一个开始。

答案 2 :(得分:0)

我将在这个问题上添加另一个答案,因为我今天已经遇到过这个问题,而且我接受的解决方案对我的情况没有帮助。

为解决我的问题,我定义了一个int,它代表ByteBuffer将保留的数据量(以字节为单位),以及Queue<Consumer<ByteBuffer>>,如下所示:< / p>

/**
 * An {@code int} representing the amount
 * of bytes that this {@link OutgoingPacket}
 * will send.
 */
private int size;

/**
 * A {@link Queue} that lazily writes data to the
 * backing {@link ByteBuffer}.
 */
private final Queue<Consumer<ByteBuffer>> queue = new ArrayDeque<>();

接下来,我创建了putByteputInt等方法

/**
 * Writes a single {@code byte} to this
 * {@link Packet}'s payload.
 *
 * @param b
 *      An {@code int} for ease-of-use,
 *      but internally down-casted to a
 *      {@code byte}.
 * @return
 *      The {@link Packet} to allow for
 *      chained writes.
 */
public OutgoingPacket putByte(int b) {
    size++;

    queue.offer(payload -> payload.put((byte) b));
    return this;
}

最后,我创建了一个send方法,其中ByteBuffer已分配并传递相应的数据。

/**
 * Transmits this {@link OutgoingPacket} to
 * a specific client.
 *
 * @param channels
 *      A variable amount of {@link AsynchronousSocketChannel}s.
 *
 * TODO: Send to {@link Client} instead.
 */
public void send(AsynchronousSocketChannel... channels) {
    /*
     * Allocate a new buffer with the size of
     * the data being added, as well as an extra
     * two bytes to account for the opcode and the
     */
    ByteBuffer payload = ByteBuffer.allocate(size + 2);

    /*
     * Write the opcode to the buffer.
     */
    payload.put((byte) opcode);

    /*
     * Write the length to the buffer.
     */
    payload.put((byte) size);

    /*
     * Add the rest of the data to the buffer.
     */
    queue.forEach(consumer -> consumer.accept(payload));

    /*
     * Flip the buffer so the client can immediately
     * read it on arrival.
     */
    payload.flip();

    /*
     * Write the buffer to the channels.
     */
    for (AsynchronousSocketChannel channel : channels) {
        channel.write(payload);
    }
}

希望这将为那些将来遇到此问题的人提供见解!