zoukankan      html  css  js  c++  java
  • java拓展----NIO

    一、介绍java中的IO

      java中的IO分许多种 

      具体介绍请往这走http://blog.51cto.com/stevex/1284437

      java IO 中的NIO的英译名为(new IO ) 他是的出现时在JDK1.4版本才有的。

      NIO 的它实则是一种非阻塞的IO,它是一种基于缓存区的IO读写。

      以前的BIO是一种基于流的读写。每次读写都消耗一个字节数据。而NIO则是一种面向块的读写。每次读写都消耗一个数据块。在操作的速度上要比BIO快许多。

    二、使用NIO

      首先介绍一下NIO的必须要知道的几个词汇

      1.通道  2.缓冲区

      通道 和 缓冲区 是 NIO 中的核心对象,几乎在每一个 I/O 操作中都要使用它们。

      通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。

      NIO同时支持多路IO复用。(多个通道连接到同一个缓冲区)

      

      NIO中程序操作的是缓冲区。文件的读取步骤将缓冲区中的数据读取全部读取到。然后将缓冲区中的缓存内容清除。NIO中文件写入操作则是将缓存中的缓存内容写入到文件中去。

    ·   以下是一个基于BIO的简单文件拷贝的实现。

    package com.demo.io.nio;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    
    public class FileChannelTest {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("C:\Users\Desktop\test.jsp");
            FileChannel foc = new FileOutputStream("C:\Users\Desktop\test.txt").getChannel();
            FileChannel fic = fis.getChannel();
            //创建一个缓冲区大小为48的ByteBuffer
            ByteBuffer bb = ByteBuffer.allocate(2);
            int br = 0;
            while((br=fic.read(bb))!= -1) {
                //bb.flip() 的调用,首先读取数据到Buffer,然后反转Buffer,接着再从Buffer中读取数据
                bb.flip();
                //告诉当前位置和极限之间是否存在任何元素(此缓冲区中有元素)
                while(bb.hasRemaining()) {
                    foc.write(bb);
                }
                System.out.println();
                //缓存满了就会清理缓存
                bb.clear();
            }
            fic.close();
            fis.close();        
        }
    }

    三、简单的文件操作

      操作流程图:

    代码:

    public class NIOFileChannel {
      public static void main(String[] args) throws IOException {
        String str = "hello world";
        //  创建一个输出流
        FileOutputStream fileOutputStream = new FileOutputStream("C:\file\file01.txt");
        //  使用输出流获取到对应的FileChannel
        FileChannel fileChannel = fileOutputStream.getChannel();
        //  创建一个缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        //  将要写入的数据放入byteBuffer中
        byteBuffer.put(str.getBytes());
        //  反转ByteBuffer
        byteBuffer.flip();
        //  将缓冲区的数据写入通道中
        fileChannel.write(byteBuffer);
        fileChannel.close();
        fileOutputStream.close();
      }
    }
    文件写入
    public class NIOFileChannelRead {
      public static void main(String[] args) throws IOException {
        //  创建文件输入流
        FileInputStream fileInputStream = new FileInputStream("C:\file\file01.txt");
        FileChannel fileChannel = fileInputStream.getChannel();
        //  创建缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(4);
        while (true) {
          //  将数据读取到fileChannel中
          int read = fileChannel.read(byteBuffer);
          if (read == -1) {
            break;
          }
          //  这里如果缓冲区满了需要清空一下才能继续读
          byteBuffer.clear();
          //  输出数据内容
          System.out.println(new String(byteBuffer.array()));
        }
        fileChannel.close();
        fileInputStream.close();
      }
    }
    文件读取
     1 public class NIOFileChannelCopy {
     2   public static void main(String[] args) throws IOException {
     3     // 创建相关流
     4     FileInputStream fileInputStream = new FileInputStream("C:\file\file01.txt");
     5     FileOutputStream fileOutputStream = new FileOutputStream("C:\file\file02.txt");
     6     //  获取相关管道
     7     FileChannel sourceCh = fileInputStream.getChannel();
     8     FileChannel destCh = fileOutputStream.getChannel();
     9 
    10     //  使用transferForm完成拷贝
    11     destCh.transferFrom(sourceCh, 0, sourceCh.size());
    12     sourceCh.close();
    13     destCh.close();
    14   }
    15 }
    文件拷贝

    四、零拷贝

    大家都说NIO的效率很高,使用到了零拷贝,至于什么是零拷贝,我们需要先探究一下Java文件读取机制。

    零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及 CPU 的拷贝时间。它的作用是在数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现 CPU 的零参与,彻底消除 CPU 在这方面的负载。实现零拷贝用到的最主要技术是 DMA 数据传输技术和内存区域映射技术。

    简单点讲就是零拷贝就是没有CPU拷贝

    BIO拷贝方式(经过4次拷贝,三次态的切换)

    1. DMA拷贝:直接内存拷贝,不使用CPU

    2.CPU拷贝:讲内存中的数据经过CPU拷贝到用户缓冲区

    3.CPU拷贝:讲数据拷贝到Socket buffer中

    4.DMA拷贝:将数据拷贝到我们的协议栈

    mmap拷贝方式(经过三次拷贝,三次态的切换)

    1. DMA 拷贝

    2.用户缓冲区与内核缓冲区存在内存映射不会进行拷贝

    3.CPU拷贝到socket buffert

    4.socket buffer DMA拷贝到协议栈

    sendFile(经过两次次拷贝,两次态的切换)

    Linux 2.1 提供

    1.DMA拷贝

    2.内核缓冲区拷贝到sockert buffer

    3.DMA拷贝到协议栈

     Linux 2.4提供

    1.DMA拷贝

    2.内核缓冲区直接DMA拷贝到协议栈

    五、后记

    个人觉得Java NIO 的API 是非常难用的。这里我推荐大家使用Netty。Netty封装的API相对来说好用很多。

  • 相关阅读:
    android spinner学习
    cookie的学习笔记三(做俩个小练习);
    Cookie的细节具体保存的有效时间
    cookie技术核心! 就是四个类的应用 搞懂这个基本上就把这个搞定了!
    学习Servlet的重要应用 在什么地方用写路径
    数组空值empty
    ios学习杂记
    ios广告封装
    Runtime
    UIImage分类,设置边框
  • 原文地址:https://www.cnblogs.com/bananafish/p/10162628.html
Copyright © 2011-2022 走看看