从 Pipe 对象的源通道读取数据时,是否真的需要 hasRemaining() 方法?

问题描述 投票:0回答:1

java.nio包中

hasRemaining()
类的
ByteBuffer
方法返回当前位置和限制之间是否有元素。

同时,

write()
类的
FileChannel
方法的文档中说:

尝试向通道写入最多

r
个字节,其中
r
是缓冲区中剩余的字节数,即调用此方法时的
src.remaining()

这是我在 java NIO 中使用管道的接收通道和源通道的主要方法:

try {
            Pipe pipe = Pipe.open();
            Runnable writer = () -> {
                try {
                    Pipe.SinkChannel sinkChannel = pipe.sink();
                    ByteBuffer writeBuffer = ByteBuffer.allocate(100);

                    for (int i = 0; i < 10; i++) {
                        String currentTime = "The current time is " + System.currentTimeMillis();
                        writeBuffer.put(currentTime.getBytes());
                        writeBuffer.flip();

                        while (writeBuffer.hasRemaining()) {
                            int writtenBytes = sinkChannel.write(writeBuffer);
                            System.out.println("Channel is writing " + writtenBytes + " bytes");
                        }

                        writeBuffer.flip();
                        Thread.sleep(150);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            };

            Runnable reader = () -> {
                try {
                    Pipe.SourceChannel sourceChannel = pipe.source();
                    ByteBuffer readBuffer = ByteBuffer.allocate(100);

                    for (int i = 0; i < 10; i++) {
                        int bytesRead = sourceChannel.read(readBuffer); 
                        byte[] stringRead = new byte[bytesRead];

                        readBuffer.flip();
                        readBuffer.get(stringRead);
                        readBuffer.flip();

                        System.out.println("Buffer reading '" + new String(stringRead) + "'");
                        Thread.sleep(150);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };

            new Thread(writer).start();
            new Thread(reader).start();

} catch (IOException e) {
            e.printStackTrace();
        }

我想知道

hasRemaining()
方法是否真的是强制性的以及我什么时候应该使用它。

java buffer nio
1个回答
0
投票

深入研究后,我发现抽象类SinkChannel是类Pipe的一部分,是由名为SinkChannelImpl的类实现的。

在后一个类中,使用 SocketChannel 对象作为通道,并且 write 方法在 SocketChannelImpl 类中实现,因为 SocketChannel也是一个抽象类。

底线是,当我调用 SinkChannel 的 write 方法时,我实际上是在调用 SocketChannelImpl 类的 write 方法。

不幸的是,文档并没有真正指定是否将所有剩余字节写入通道,引用:“某些类型的通道,根据其状态,可能只写入部分字节,或者可能根本不写入”,代码也被混淆了,需要一些时间才能知道它是如何工作的。

所以我将在写入后使用compact方法,这样万一某些字节未写入,它们将被移动到缓冲区的beginning

© www.soinside.com 2019 - 2024. All rights reserved.