zoukankan      html  css  js  c++  java
  • 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();
        }
  • 相关阅读:
    EditPlus 4.3.2502 中文版已经发布(12月5日更新)
    EditPlus 4.3.2499 中文版已经发布(11月21日更新)
    为什么有负频率,什么是相位谱 —— 关于傅立叶变换的随笔
    对“善于提问,主动解决问题”的程序员的吐槽
    .NET事件监听机制的局限与扩展
    .NET陷阱之六:从枚举值持久化带来大量空间消耗谈起
    深入挖掘.NET序列化机制——实现更易用的序列化方案
    在VMWare中建立Hadoop虚拟集群的详细步骤(使用CentOS)
    微信分享
    如何导入ShareSDK的sample
  • 原文地址:https://www.cnblogs.com/charlypage/p/9196588.html
Copyright © 2011-2022 走看看