Java NIO Channel通道和IO中流的不同;
1.双向通道,既可以读取也可以写入;
2.通道可以异步读写
3.通道中的数据总是要先读到一个Buffer.或总是要从一个Buffer中写入
一.Channel的实现类
FileChannel: 从文件中读写数据;
DatagramChannel: 能通过UDP读写网络中的数据;
SocketChannel: 能从TCP读写网络中的数据;
ServerSocketChannel : 可以监听新建立的TCP连接,和Web服务器一样,每建立一个新的连接都会创建一个SocketChannel
基本的 Channel 示例
下面是一个使用FileChannel读取数据到Buffer中的示例:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buf.flip();
while(buf.hasRemaining()){
System.out.print((char) buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();
注意 buf.flip() 的调用,首先读取数据到Buffer,然后反转Buffer,接着再从Buffer中读取数据。下一节会深入讲解Buffer的更多细节。
二.Scatter/Gather
scatter/Gather用于将传输的数据分开处理的的场合,
Java NIO开始支持scatter/gather,scatter/gather使用描述从Channel中读取或者写入到Channel的操作
分散(scatter) 从Channel中读取时将读取的数据写入多个buffer中,Chanel将从Channel中读取的数据scatter到多个Buffer;
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,Channel将多个Buffer中的数据gather后发送到Channel;
Scattering Reads
Scattering Reads是指从一个channel读取到多个Buffer中.使用read(bufferArray)方法可以实现,read方法按照buffer在数组中的顺序从channel中读取的数据写入到buffer,当一个buffer写满后会接着向另一个buffer中写(写满之后才能变更,不适合动态大小的消息,使用时,注意buffer大小的确定).
Gathering Writes
指将多个buffer中的数据写入同一个channel,和Scattering Reads一样先将多个buffer整合到一个BufferArray中然后使用write(BufferArray)方法按数组顺序写入到channel中,注意只有在position和limit中的数据会被写入到channel中,因此和Scattering Reads比起来Gathering Writes可以很好的处理动态大小的消息(笔记:利用limit和position实现)
三.Channel to Channel Transfers 通道传输
在Java NIO中如果是一个FileChannel可以直接从一个channel传递数据到其他地方,FileChannel类通过transferTo()和transferFrom()方法来实现这个
transferFrom()
这个方法可以从一个source channel(源通道)传递数据到FileChannel中,使用方法:toChannel.transferFrom(fromChannel,position,count),其中position参数表示从目标文件的写入位置,count表示最大的传输字节,如果source channel的剩余空间小于最大传输字节,传输的字节要小于请求的字节数,此外,一些SocketChannel实现中,SocketChannel只能传输已经在内存缓冲区准备好的数据即使SocketChannel中有更多的数据存在,因此SocketChannel可能不会将所有数据(count个字节)全部传输到FileChannel中
demo
transferTo()
这个方法可以从一个FileChannel传递数据到其他channel中,和transferFrom()一样,SocketChannel的问题也一样,SocketChannel实现会从FileChannel中传递字节知道buffer被填满,然后停止