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()
方法是否真的是强制性的以及我什么时候应该使用它。
深入研究后,我发现抽象类SinkChannel是类Pipe的一部分,是由名为SinkChannelImpl的类实现的。
在后一个类中,使用 SocketChannel 对象作为通道,并且 write 方法在 SocketChannelImpl 类中实现,因为 SocketChannel也是一个抽象类。
底线是,当我调用 SinkChannel 的 write 方法时,我实际上是在调用 SocketChannelImpl 类的 write 方法。
不幸的是,文档并没有真正指定是否将所有剩余字节写入通道,引用:“某些类型的通道,根据其状态,可能只写入部分字节,或者可能根本不写入”,代码也被混淆了,需要一些时间才能知道它是如何工作的。
所以我将在写入后使用compact方法,这样万一某些字节未写入,它们将被移动到缓冲区的beginning。