Java 净读取字节的确切数目

Java 净读取字节的确切数目,java,netty,Java,Netty,我正在扩展,希望读取确切的字节数 public class Reader extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg){ ByteBuf b = (ByteBuf) msg; byte size = b.readByte(); //Now I want to

我正在扩展,希望读取确切的字节数

public class Reader extends ChannelInboundHandlerAdapter{

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg){
        ByteBuf b = (ByteBuf) msg;
        byte size = b.readByte();
        //Now I want to read exactly size bytes from the channel
        //and then again read the number of bytes and read the bytes...
    }

}

问题是,我们可能会从中读取的字节数少于所需的字节数。如何阅读?

仅用于阅读,您可以使用
b.readSlice(大小)
。 但是,正如您所提到的,缓冲区可能还没有足够的数据来存储消息。因此,您需要在创建消息之前完全使用数据。对于这种情况,我建议您使用内置的
ByteToMessageDecoder
处理程序。它将为您处理低级字节。因此,使用
ByteToMessageDecoder
时,您的代码将如下所示:

class Reader extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        byte size = in.readByte();
        if (in.readableBytes() < size) {
           in.resetReaderIndex();
           return;
        }

        ByteBuf bb = in.readSlice(size);
        //make whatever you want with bb
        Message message = ...; 
        out.add(message);
    }
}
类读取器扩展ByteToMessageDecoder{
@凌驾
受保护的无效解码(ChannelHandlerContext ctx、ByteBuf输入、列表输出)引发异常{
字节大小=in.readByte();
if(in.readableBytes()

因此,在本例中,您读取了消息需要读取的字节数-
size
。然后检查
缓冲区中的
是否有足够的数据可以使用。如果不是,则将控件返回到ByteToMessageDecoder
,直到它读取更多。然后重复,直到有足够的数据来构建消息。

事实上,是的。谢谢。但是与之间的区别是什么呢?何时使用哪个?@St.Antario请查看
ReplayingDecoder
javadocs。它有一个很好的例子解释。简而言之,
ReplayingDecoder
做的更多,您不需要在.readableBytes()中检查
。但是,价格是-性能较低。ReplayDecoder可以帮助您处理底层流数据的复杂情况,例如数据不足。如果您不太关心性能,它将大大降低代码逻辑的复杂性。