【摘要】 Q: NIO和标准IO有什么区别?A:标准IO, 基于字节流和字符流进行操作,阻塞IO。NIO基于通道channel和缓冲区Buffer进行操作,支持非阻塞IO,提供选择器§ JavaNIO核心3组件:§ Channels 通道Q: 通道Channel对象能同时做读写操作吗?还是说需要像标准IO那样,需要同时创建input和output对象才能做读写操作?A:通道Channel是双向的, 既…
Q: NIO和标准IO有什么区别?
A:
- 标准IO, 基于字节流和字符流进行操作,阻塞IO。
- NIO基于通道channel和缓冲区Buffer进行操作,支持非阻塞IO,提供选择器
§ JavaNIO核心3组件:
§ Channels 通道
Q: 通道Channel对象能同时做读写操作吗?
还是说需要像标准IO那样,需要同时创建input和output对象才能做读写操作?
A:
通道Channel是双向的, 既可以从channel中读数据,也可以写数据。
可以看到既能调用read也能调用write,且需要依赖缓冲区buffer。
FileChannel fileChannel = FileChannel.open(new File("a.txt").toPath());
ByteBuffer buf = ByteBuffer.allocate(1024);
fileChannel.read(buf);
fileChannel.write(buf);
- 注意上图上,fileChannel.read(buf)是将a.txt里的数据读到buf, 即a.txt->buf
- fileChannel.write(buf)是将buf里的数据写入到a.txt中, 即buf->a.txt,不要搞反啦!
- 通道和缓冲区的关系
Q: 通道支持异步读写吗
A: 支持。
Q: 通道的读写是否必须要依赖缓冲区buffer?
A: 一般都是依赖buffer的。 但也支持2个管道之间的传输,即管道之间直接读写。
String[] arr=new String[]{"a.txt","b.txt"};
FileChannel in=new FileInputStream(arr[0]).getChannel();
FileChannel out =new FileOutputStream(arr[1]).getChannel();
// 将a.txt中的数据直接写进b.txt中,相当于文件拷贝
in.transferTo(0, in.size(), out);
常用的几种Channel
- FileChannel
Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。
FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下
创建方式
RandomAccessFile file = new RandomAccessFile("D:/aa.txt");
FileChannel fileChannel = file.getChannel();
- SocketChannel
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。
支持非阻塞模式socketChannel.configureBlocking(false)。
可以通过以下2种方式创建SocketChannel:
打开一个SocketChannel并连接到互联网上的某台服务器。
一个新连接到达ServerSocketChannel时,会创建一个SocketChannel
创建方式
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("192.168.1.100",80));
- ServerSocketChannel
Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样。ServerSocketChannel类在 java.nio.channels包中。
SocketChannel和ServerSocketChannel的区别: 前者用于客户端,后者用于服务端
创建方式:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket.bind(new InetSocketAddress(80));
serverSocketChannel.configureBlocking(false);
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
if(socketChannle != null)
doSomething...
}
Buffer缓冲区
- 我们真正要把数据拿到或者要写数据, 实际上都是通过buffer进行操作的。
文件 <-> buffer <-> 数据 - buffer是1个即可读也可写的缓冲区,拥有读写2种模式。
- buffer的capacity属性限定了每个buffer的最大容量,下面的1024就是capacity。
ByteBuffer buf = ByteBuffer.allocate(1024);