Java - Transferring big files over channels - NIO
java, nio
Solution
The correct way to copy channels via buffers is as follows:
while (in.read(buffer) >= 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
This takes care of all the corner cases including read length != write length and having data left over at the end of the input.
NB that is for blocking mode. If you are in non-blocking mode you should return to the `select()` loop if read() or write() returns zero.
Problem
I have to transfer ~100MB of data over ServerSocket using NIO, but I can't figure out how to do this without transfer breaking at any place / keeping the state of transfer. My first idea was to send the size of file, apparently I can't send size of that big files because it wont even fit on RAM at once. Then I thought, why not just transfer til nothing is received, but thats when problem comes in. Even if I am writing server-sided data all the time ``` FileChannel fc = new FileInputStream(f).getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while(fc.read(buffer) > 0) { buffer.flip(); while(channel.write(buffer) > 0); buffer.clear(); } ``` but because there have to be breaks in file transfer some time reading the data constantly and breaking when nothing is available was bad idea. I can't figure out how could I possibly tell the client if theres still data available without having to send each slice of data as new packet with opcode etc., or is it even possible? I am also wondering if theres better way to send whole buffer than below ``` while(channel.write(buffer) > 0); ```