内容目录
3.4.1 Channel-to-Channel传输
由于经常需要从一个位置将文件数据批量传输到另一个位置,FileChannel
类添加了一些优化方法来提高该传输过程的效率:
public abstract class FileChannel extends AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel { // 这里仅列出部分API public abstract long transferTo (long position, long count, WritableByteChannel target) public abstract long transferFrom (ReadableByteChannel src, long position, long count) }
transferTo()
和transferFrom()
方法允许将一个通道交叉连接到另一个通道,而不需要通过一个中间缓冲区来传递数据。只有FileChannel
类有这两个方法,因此Channel-to-Channel传输中通道之一必须是FileChannel
。您不能在socket通道之间直接传输数据,不过socket通道实现WritableByteChannel
和ReadableByteChannel
接口,因此文件的内容可以用transferTo()
方法传输给一个socket通道,或者也可以用transferFrom()
方法将数据从一个socket通道直接读取到一个文件中。
直接的通道传输不会更新与某个FileChannel
关联的position
值。请求的数据传输将从position
参数指定的位置开始,传输的字节数不超过count
参数的值。实际传输的字节数会由方法返回,可能少于您请求的字节数。
对于传输数据来源是一个文件的transferTo()
方法,如果position + count
的值大于文件的size
值,传输会在文件尾的位置终止。假如传输的目的地是一个非阻塞模式的socket通道,那么当发送队列(send queue)满了之后传输就可能终止,并且如果输出队列(output queue)已满的话可能不会发送任何数据。类似地,对于transferFrom()
方法:如果来源src
是另外一个FileChannel
并且已经到达文件尾,那么传输将提早终止;如果来源src
是一个非阻塞socket通道,只有当前处于队列中的数据才会被传输(可能没有数据)。由于网络数据传输的非确定性,阻塞模式的socket也可能会执行部分传输,这取决于操作系统。许多通道实现都是提供它们当前队列中已有的数据而不是等待您请求的全部数据都准备好。
此外,请记住:如果传输过程中出现问题,这些方法也可能抛出java.io.IOException
异常。
Channel-to-Channel传输是可以极其快速的,特别是在底层操作系统提供本地支持的时候。某些操作系统可以不必通过用户空间传递数据而进行直接的数据传输。对于大量的数据传输,这会是一个巨大的帮助(参见例 3-6)。
/*
*例 3-6 使用通道传输进行文件连结
*/
package com.ronsoft.books.nio.channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.Channels;
import java.io.FileInputStream;
/**
* Test channel transfer. This is a very simplistic concatenation
* program. It takes a list of file names as arguments, opens each
* in turn and transfers (copies) their content to the given
* WritableByteChannel (in this case, stdout).
*
* Created April 2002
* @author Ron Hitchens (ron@ronsoft.com)
*/
public class ChannelTransfer {
public static void main (String [] argv) throws Exception {
if (argv.length == 0) {
System.err.println ("Usage: filename ...");
return;
}
catFiles (Channels.newChannel (System.out), argv);
}
// Concatenate the content of each of the named files to
// the given channel. A very dumb version of 'cat'.
private static void catFiles (WritableByteChannel target, String [] files) throws Exception {
for (int i = 0; i < files.length; i++) {
FileInputStream fis = new FileInputStream(files [i]);
FileChannel channel = fis.getChannel();
channel.transferTo(0, channel.size(), target);
channel.close();
fis.close();
}
}
}
0 条评论
撰写评论