- 一、相关概念
- 1、阻塞和非阻塞
- 2、同步和异步
- 3、IO模型
- 二、NIO的使用
- 1、NIO优点
- 2、Channel(通道)
- 3、Buffer(缓冲区)
- 4、Selector(多路复用器)
- 5、使用示例
- 三、jdk1.7的 NIO(改进)
- 1、 Path、Paths和Files工具类
- 2、Files工具类常用方法
- 3、使用示例
一、相关概念 1、阻塞和非阻塞相比于之前讲的输入流、输出流、缓冲流等传统IO,jdk1.4提供的NIO在效率上会更高,jdk1.7时,提供了Files工具类,支持异步Channel的IO,效率更高
区别:IO面向流,NIO面向缓冲区
- 阻塞:线程访问资源时,资源未准备好,持续等待
- 非阻塞:线程访问资源时,资源未准备好,直接相应,不会等待
- 同步:访问数据时,主动请求并等待IO *** 作完成
- 异步:访问数据时,请求后可以继续处理其他任务
-
传统BIO模型
同步阻塞,IO在执行读写时,线程被阻塞,等待读写完成
-
伪异步IO模型
和同步阻塞类似,加入了线程池维护IO现在,效率相对BIO更高
-
NIO模型
是一种同步非阻塞IO,面向缓冲区进行 *** 作,单个线程通过Selector(多路复用器)监听多个通道事件,实现高效
- 通过注册Channel到Selector上的状态来实现客户端与服务端的通信
- Channel中数据的读取是通过Buffer,是一种非阻塞的读取方式(轮询看数据准备好没)
- Selector多路复用器,单线程,线程资源开销小
区别于IO中读取数据时,会发生阻塞等待数据,NIO的Channel对象可以通过不同的阻塞行为,判断进行相应的 *** 作,实现非阻塞通道
Channel`是双向的,可以读也可以写
-
Channel接口的相关实现类
FileChannel:支持文件 *** 作
Pipe.SinkChannel、Pipe.SourceChannel:支持线程间通信
ServerSocketChannel:支持TCP网络通信
DategramChannel:支持UDP网络通信
-
创建方法:
根据流节点(如InputStream、OutputStream)的getChannel()方法来返回对应的 Channel(如FileChannel等)
-
常用方法:
map():用于将 Channel 对应的部分或全部数据映射成ByteBuffer
read():从 Buffer 读入数据
write():从 Buffer 写入数据
是一个缓冲区,也是一个容器,像一个数组,可以保存多个同类型数据在Channel读写数据时,中间需要经过Buffer
Buffer的使用
-
3个重要概念:
容量(capacity):Buffer的最大数据容量,创建后不能改变
界限(limit):位于limit后的区域,不能被读写
位置(position):指明下一个被读或者被写入的位置索引
- 当 Buffer 装入数据结束,调用flip()方法,让指针复位,即上图已经读写区域清除,为输出数据做准备
- 当 Buffer 输出数据结束,调用clear()方法,将整个区域设为尚未读写区域,为再次向 Buffer 中装入数据做准备(数据并未清除)
和 Channel 相互配合使用,可以监听 Channel 的四种状态,监听到对应的状态时,才允许对 Channel进行相应的 *** 作
-
Read:可读
-
Write:可写
-
Connect:客户端连接成功
-
Accept:准备好进行连接
读取文件
public static void main(String[] args) throws IOException{ File fiel = new File("test.txt"); // 创建一个文件输入流,并获得文件输入流对应的管道 FileChannel inChannel = new FileInputStream(file).getChannel(); // 创建一个字节缓冲区(Channel的读取都要通过缓冲区完成) ByteBuffer buf = ByteBuffer.allocate(1024); // 将数据写入缓冲区 int readCount = inChannel.read(buf); while((fileChannel.read(buf)) > -1){ // 装入数据完成,让指针复位,为输出数据做准备 buf.flip(); while(bug.hasRemaining()){ // 打印 System.out.print((char)buf.get()) } // 清除缓冲区之前数据,复位标记位为0,配合 filp()使用 buf.compact(); } }三、jdk1.7的 NIO(改进)
1、 Path、Paths和Files工具类提供了全面的文件IO和文件系统访问
基于异步Channel的IO
- Path:该接口代表一个与平台无关的平台路径
- Paths:获取Path对象
- Files: *** 作文件的工具类
-
readAllBytes(Path p):获取文件内容(byte)
该方法可以和String(byte[] b, String utf-f)一起使用,转字符串
-
write(Path p, String):将 String 写入到 p 文件中
-
copy(Path p, OutputStream out):将p文件内容复制到输出流 out 的文件中(源码里调了copy(in, out),一个输入流,一个输出流)
-
delete(Path p):将 p 文件删除
获取文件内容
public static void main(String[] args){ // 文件路径 Path p = Paths.get("test.txt"); // 读取 test.txt 文件的内容,放到 byte数组中 byte[] byt = Files.readAllBytes(p); // 将字节数组转字符串并打印 System.out.print(new String(byt, "utf8")); }
文件复制
public static void main(String[] args){ // 文件路径 Path p = Paths.get("test.txt"); // 字符输出流 FileOutputStream out = new FileOutputStream("newTest.txt"); // 将 test.txt 复制到 newTest.txt Files.copy(p, out); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)