美文网首页
IO流 对比和文本操作

IO流 对比和文本操作

作者: 黄靠谱 | 来源:发表于2019-02-14 18:10 被阅读5次

    参考

    Demo 源码:
    https://github.com/huangzhenshi/IO_NIO_NIO2Dem

    概述

    • BIO基于流的单向操作
    • NIO是通过Channel和Buffer缓冲池双向操作
    • AIO Channel来操作,AIO依赖操作系统的实现来将来回调

    IO流的主要应用场景:

    1. 文件读写和存储操作(文本、图片、音频、视频文件)
    2. Socket编程(TCP、UDP)(聊天室、图片和文件上传、下载)
    3. 跨系统的交互:Netty(Rocketmq、Dubbo)

    三种流的特点

    1. 读写文件方面,随着JDK的发展,陆续完善了IO流的读写功能,所以单就文件的读写而言,版本越高,API越方便,代码越简洁
    2. BIO:阻塞式,适合小并发,大文件的传输,性能最好
    3. NIO:异步非阻塞,适合大并发,小文件的传输,多路绑定一个Selector,循环遍历Selector线程来响应所有子线程的事件,比如微信的文字聊天
    4. AIO:异步将来式、异步回调式,适合大并发,重操作,大文件传输的业务场景

    3种IO流的区别

    1. 文件读写删等操作:
    • BIO最原始,文件读写操作:输入文件、输出文件、输入流、输入缓冲流、输出流、输出缓冲流,完成一个读写操作

    • NIO基于JDK1.4,但并不支持非阻塞的文件操作,基于FileChannel和各种Buffer,存储内容和操作管道解耦,而不像BIO把这些操作都耦合在流上面,Channel支持很多高级操作,比如transferTo三行代码就能实现从一个文件读取数据到另外一个文件

    • AIO基于JDK1.7,支持多个的功能:基于Path和Files的文件和文件夹的复制、移动、删除(都不需要FileChannel),获取和改变文件的属性(RW读写属性、最后修改时间和大小),支持监听文件的变化,还封装了很多API操作文件。

    • AIO不基于工具类,而是基于AsynchronousFileChannel支持两种文件读写的操作:将来回调式和非阻塞式Future对象的方式。

    1. Socket编程:BIO不适合高并发,但是代码简单,响应速度也快。高并发小流量的操作交给NIO,高并发重操作交给AIO
    • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解;
      BIO的编程方式简单粗暴,就是阻塞式:服务端阻塞式监听到一个客户端,就单独开启一个子线程阻塞式的监听客户端的消息,客户端连接成功以后,也是阻塞式的监听服务端写入的消息

    • NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持;
      NIO的编程方式非阻塞式循环遍历:是服务端和客户端各自都注册一个Selector,然后循环遍历Selector的事件

    • AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持
      AIO的编程方式分为2种,将来式和回调式,回调式的方法用的监听回调类比较多,比如AcceptHandler、ReadHandler、WriteHandler、ConnectHandler,但是每个回调类的功能单一

    核心类演示

    BIO:输入流:输出流、文件流、缓冲流

        FileInputStream fis= new FileInputStream(new File(fileFrom));
        InputStreamReader isr = new InputStreamReader(fis, "GBK");
        BufferedReader br = new BufferedReader(isr);
        FileOutputStream fos = new FileOutputStream(fileTo);
        OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
        BufferedWriter bw = new BufferedWriter(osw);
        String input;
        while ((input = br.readLine()) != null) {
            System.out.println(input);
            bw.write(input);
            bw.newLine();
        }
    

    NIO:

    • Channel: FileChannel(阻塞式文件操作)、DatagramChannel(UDP)、SocketChannel(TCP)、ServerSocketChannel(TCP)
    • Buffer:ByteBuffer、CharBuffer
    • Selector:
    • Pipe: 只支持数据单向流动的channel
    1. 利用函数transferFrom复制文本
        RandomAccessFile fromFile = new RandomAccessFile(fileFrom, "rw");  
        FileChannel      fromChannel = fromFile.getChannel();  
        RandomAccessFile toFile = new RandomAccessFile(fileTo, "rw");  
        FileChannel      toChannel = toFile.getChannel();  
        long position = 0;  
        long count    = fromChannel.size();  
        toChannel.transferFrom(fromChannel, position, count);  
    
    1. 通过常规的Channel、Buffer进行文本的复制,2个Channel对一个ByteBuffer进行操作
        RandomAccessFile aFile = new RandomAccessFile(fileFrom, "rw");
        RandomAccessFile toFile = new RandomAccessFile(fileTo, "rw");  
        FileChannel inChannel = aFile.getChannel();
        FileChannel toChannel = toFile.getChannel();  
        ByteBuffer buf = ByteBuffer.allocate(1024);
        while (inChannel.read(buf) != -1) {
          buf.flip();  
          toChannel.write(buf);
          buf.clear(); 
        }
    

    AIO:

    • Path:可以指向文件或文件夹,很多情况下,可以用Path来代替File类,和Files类配合着用。
    • Files 工具类: readAllLines ,write ,copy,deleteIfExists
    • AsynchronousFileChannel: 用于文件异步读写;
    • AsynchronousSocketChannel: 客户端异步socket;
    • AsynchronousServerSocketChannel: 服务器异步socket。
      文本复制
        Path sourcePath= Paths.get(fileFrom);  
        Path descPath= Paths.get(fileTo);  
        Files.copy(sourcePath, descPath); 
    

    相关文章

      网友评论

          本文标题:IO流 对比和文本操作

          本文链接:https://www.haomeiwen.com/subject/zvkyeqtx.html