栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

IO/NIO — NIO

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

IO/NIO — NIO

IO/NIO — NIO
        • 一、相关概念
          • 1、阻塞和非阻塞
          • 2、同步和异步
          • 3、IO模型
        • 二、NIO的使用
          • 1、NIO优点
          • 2、Channel(通道)
          • 3、Buffer(缓冲区)
          • 4、Selector(多路复用器)
          • 5、使用示例
        • 三、jdk1.7的 NIO(改进)
          • 1、 Path、Paths和Files工具类
          • 2、Files工具类常用方法
          • 3、使用示例

相比于之前讲的输入流、输出流、缓冲流等传统IO,jdk1.4提供的NIO在效率上会更高,jdk1.7时,提供了Files工具类,支持异步Channel的IO,效率更高

区别:IO面向流,NIO面向缓冲区

一、相关概念 1、阻塞和非阻塞
  • 阻塞:线程访问资源时,资源未准备好,持续等待
  • 非阻塞:线程访问资源时,资源未准备好,直接相应,不会等待
2、同步和异步
  • 同步:访问数据时,主动请求并等待IO操作完成
  • 异步:访问数据时,请求后可以继续处理其他任务
3、IO模型
  • 传统BIO模型

    同步阻塞,IO在执行读写时,线程被阻塞,等待读写完成

  • 伪异步IO模型

    和同步阻塞类似,加入了线程池维护IO现在,效率相对BIO更高

  • NIO模型

    是一种同步非阻塞IO,面向缓冲区进行操作,单个线程通过Selector(多路复用器)监听多个通道事件,实现高效

二、NIO的使用 1、NIO优点
  • 通过注册Channel到Selector上的状态来实现客户端与服务端的通信
  • Channel中数据的读取是通过Buffer,是一种非阻塞的读取方式(轮询看数据准备好没)
  • Selector多路复用器,单线程,线程资源开销小
2、Channel(通道)

区别于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 写入数据

3、Buffer(缓冲区)

是一个缓冲区,也是一个容器,像一个数组,可以保存多个同类型数据在Channel读写数据时,中间需要经过Buffer

Buffer的使用

  • 3个重要概念:

    容量(capacity):Buffer的最大数据容量,创建后不能改变

    界限(limit):位于limit后的区域,不能被读写

    位置(position):指明下一个被读或者被写入的位置索引

  • 当 Buffer 装入数据结束,调用flip()方法,让指针复位,即上图已经读写区域清除,为输出数据做准备
  • 当 Buffer 输出数据结束,调用clear()方法,将整个区域设为尚未读写区域,为再次向 Buffer 中装入数据做准备(数据并未清除)
4、Selector(多路复用器)

和 Channel 相互配合使用,可以监听 Channel 的四种状态,监听到对应的状态时,才允许对 Channel进行相应的操作

  • Read:可读

  • Write:可写

  • Connect:客户端连接成功

  • Accept:准备好进行连接

5、使用示例

读取文件

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(改进)

提供了全面的文件IO和文件系统访问

基于异步Channel的IO

1、 Path、Paths和Files工具类
  • Path:该接口代表一个与平台无关的平台路径
  • Paths:获取Path对象
  • Files:操作文件的工具类
2、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 文件删除

3、使用示例

获取文件内容

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);
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/490483.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号