JAVA的NIO的新特性和小Demo,进一步了解NIO

1.为什么要用NIO

NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。 原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。正如前面提到的,原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。

2.NIO核心对象:缓冲区

 

什么是缓冲区? Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。 在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。

最常用的缓冲区类型是 ByteBuffer。一个 ByteBuffer 可以在其底层字节数组上进行 get/set 操作(即字节的获取和设置)。

3.NIO核心对象:通道

什么是通道? Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。 正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

通道类型: 通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。

实例:

NIO读文件

@Test
    public void read() throws Exception {
        //第一步是获取通道,我们从FileInpustream获取通道
        FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt");
        FileChannel channel = fin.getChannel();
        //下一步是创建缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);


        StringBuilder sb = new StringBuilder();

        //通过通道读取文件内容到缓冲区,未读到文件最后就一直读取
        while ((channel.read(buf)) != -1) {
            //调用flip之后,读到指针到缓存头部,并且设置最多只能读出之前写入的数据长度(而不是整个缓存容量的大小)
            buf.flip();
            //循环判断缓冲区是否还有可用数据


            while (buf.hasRemaining()) {
                char b = (char) buf.get();

                sb.append(b);
                //读取缓冲区内容,转换成CHAR型


            }
            System.out.println(String.valueOf(sb));
            //compact():只会清除已经读过的数据 任何未读的数据都被移到缓冲区的其实出
            //新写入的数据将放到缓冲区未读数据的后面
            buf.compact();

        }


    }

NIO写文件

@Test
    public void write() throws IOException {
      String  mess[] = {"09","099","665","655","355"};
        //创建文件字节输出流
        FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test2.txt");
        //从字节流中获取通道
        FileChannel channel = fout.getChannel();
        //创建缓冲区对象 (allocate分配)
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //通过管道往缓冲区写数据
        for (int i = 0; i <mess.length ; i++) {
            buffer.put(mess[i].getBytes());
        }

        //改变缓冲区指针
        buffer.flip();

        //把缓冲区内容写入到通道
        channel.write(buffer);

        //紧凑
        buffer.compact();

        //关流
        fout.close();


    }

 

NIO读写结合

@Test
    public void Nio() throws IOException {
        //创建字节输入流
        FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt");

        //创建字节输出流
        FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test3.txt");

        //创建输入通道
        FileChannel finChannel = fin.getChannel();
        //创建输出通道
        FileChannel foutChannel = fout.getChannel();

        //创建Nio的缓冲流
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        //循环
        while (true) {
            //clear方法重置缓冲区,使他可以接受读入的数据()position
            buffer.clear();

            //从输入通道读取内容到缓冲区
            int r = finChannel.read(buffer);
            //如果读取到文件的结尾 返回的结果为-1
            if (r == -1){
                break;
            }
                //flip()方法可以一步步读取缓冲区的内容
                buffer.flip();



            foutChannel.write(buffer);


        }
        //关流
        fin.close();
        fout.close();
    }

 

posted @ 2018-06-18 22:34  城南少年与猫  阅读(213)  评论(0编辑  收藏  举报