The hasRemaining()
method of the ByteBuffer
class in java.nio package returns whether there are any elements between the current position and the limit.
At the same time, the documentation of the write()
method of FileChannel
class says:
An attempt is made to write up to
r
bytes to the channel, wherer
is the number of bytes remaining in the buffer, that is,src.remaining()
, at the moment this method is invoked.
This is my main method where I am using a sink channel and source channel of pipes in 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();
}
I would like to know if the hasRemaining()
method is really mandatory or not and when should I use it.
After investigating a little deeper I found that the abstract class SinkChannel
that is a part of the class Pipe
is implemented by a class named SinkChannelImpl
.
In the latter class, a SocketChannel
object is used as a channel, and the write method is implemented in the SocketChannelImpl
class since
SocketChannel
is an abstract class too.
Bottom line is that when I call the write()
method of the SinkChannel
I am actually calling the write()
method of the SocketChannelImpl
class.
Unfortunately, the documentation does not really specify if all of the remaining bytes will be written to the channel or not, quote:
Some types of channels, depending upon their state, may write only some of the bytes or possibly none at all
Also the code is obfuscated and will take some time to know how it works.
So I will be using the compact()
method after the write so in case some of the bytes are not written they will be moved to the beginning of the buffer.