在 Java NIO 中,如果两个 Channel 中的一个是 FileChannel,那么这两个 Channel 可以直接传送数据。FileChannel 提供了一个 transferTo() 方法和一个 transferFrom() 方法可以做到这些。
1、transferFrom()
FileChannel.transferFrom() 方法可以从一个源 Channel 中向这个 FileChannel 中传送数据,示例如下:
RandomAccessFile fromFile = new RandomAccessFile("F:\\temp\\source.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("F:\\temp\\file.txt", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
toChannel.transferFrom(fromChannel, position, count);
fromFile.close();
toFile.close();
入参中的 position 和 count,指定了从目的 Channel 的哪个位置开始(position)以及向这个 FileChannel 中最多传送的字节数(count)。如果目的 Channle 中没有这么多个字节,则不传送那么多个,即只传送 limit - position 个字节。
此外要注意,在一些 SoketChannel 的实现中,SocketChannel 只会传输此时此刻其 Buffer 中已准备好的数据,此后出现在该 SocketChannel 中的那些有意义的数据则不会被传输。因此,SocketChannel 可能不会将请求的所有数据(count 个字节)全部传输到FileChannel中,而其实这些数据在 SocketChannel 中都有,只不过不是同时出现的。
2、transferTo()
transferTo() 方法可以从一个 FileChannel 中向其他类型的 Channel 中传送数据,示例如下:
RandomAccessFile fromFile = new RandomAccessFile("F:\\temp\\source.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile("F:\\temp\\file.txt", "rw");
FileChannel toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);
fromFile.close();
toFile.close();
SocketChannel 在 transferTo() 方法中依然有上面提到的那个问题,SocketChannel 只能传送 Send Buffer 中的数据,而一旦 Send Buffer 满了,就会停止,导致后面的数据无法传输。