zoukankan      html  css  js  c++  java
  • Java文件与io——NewIO

    为啥要使用NIO?

    NIO的创建目的是为了让JAVA程序员可以实现高速I/O而无需编写自定义的本机代码。NIO将最耗时的I/O操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度

    流与快的比较

    原来的I/O库(在java.io.*中)与NIO最重要的区别是数据打包和传输的方式,原来的I/O以流的方式处理数据,而NIO以快的方式处理数据。

    面向流的I/O系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。不利的一面是,面向流的I/O通常相当慢。

    一个面向快的I/O系统以快的形式处理数据。每一个操作都在一步中产生或消费一个数据块。按快处理数据比按(流式的)字节处理数据要快的多,但是面向快的I/O缺少一些面向流的I/O所具有的优雅性和简单性。

    缓冲区

    在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读取到缓冲区中的,在写入数据时,它是写入到缓冲区中的。任何时候访问NIO中的数据,都是将它放到缓冲区中

    缓冲区实质上一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。

    缓冲区类型

    最常用的缓冲区类型是ByteBuffer。一个ByteBuffer可以在其底层字节数组上进行get/set操作(即字节的获取和设置)。ByteBuffer不是NIO中唯一的缓冲区类型。事实上,对于每一种基本java类型都有一种缓冲区类型:

    ByteBuffer   CharBuffer  ShortBuffer  IntBuffer  LongBuffer  FloatBuffer  DoubleBuffer

    缓冲区内部细节:

    状态变量

    可以用三个值指定缓冲区在任意时刻的状态:

    position                             limit         capacity

    public class NIIODemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("----------");
            ByteBuffer buf=ByteBuffer.allocate(10);
            System.out.println("position="+buf.position());
            System.out.println("limit="+buf.limit());
            System.out.println("capacity="+buf.capacity());
            System.out.println("----------");
            buf.put((byte) 10);
            byte[] bs={20,30,40};
            buf.put(bs);
            ByteBuffer buf1=ByteBuffer.allocate(10);
            System.out.println("position="+buf.position());
            System.out.println("limit="+buf.limit());
            System.out.println("capacity="+buf.capacity());
            System.out.println("----------");
            buf.flip();//反转,将position回到初始位置,limit等于position的值
            ByteBuffer buf2=ByteBuffer.allocate(10);
            System.out.println("position="+buf.position());
            System.out.println("limit="+buf.limit());
            System.out.println("capacity="+buf.capacity());
            System.out.println("----------");
            
            //取值
            //返回当前位置与限制之间的元素
            for(int i=0;i<buf.remaining();i++){
                System.out.println(buf.get(i));
            }
        }
    
    }

    通道:Channel

    Channel是一个对象,可以通过它读取和写入数据。拿NIO与原来的I/O做个比较,通道就像是流。

    正如前面提到的,所有数据都通过Buffer对象来处理。永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

    /**
     * 文件的读写操作:1.内存映射方式(最快)  2.NIO的文件通道读写(第二块)  3.传统的IO读写(最慢)
     * @author Administrator
     *
     */
    public class FileCopyDemo {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            //copy(new File("c:\aaa.txt"),new File("c:\aaa\aaa.txt"));
            RandomAccessFileDemo();
        }
        
        public static void copy(File src,File dest){
            try {
                FileInputStream in=new FileInputStream(src);
                FileOutputStream out=new FileOutputStream(dest);
                FileChannel fcin=in.getChannel();//获取文件通道
                FileChannel fcout=out.getChannel();
                
                ByteBuffer buf=ByteBuffer.allocate((int)src.length());
                fcin.read(buf);
                buf.flip();
                fcout.write(buf);
                
                fcin.close();
                fcout.close();
                in.close();
                out.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
        public static void RandomAccessFileDemo(){
            try {
                RandomAccessFile in=new RandomAccessFile(new File("c:\aaa.txt"),"r");
                RandomAccessFile out=new RandomAccessFile(new File("c:\aaa\aaa.txt"),"rw");
                
                FileChannel inChannel=in.getChannel();
                FileChannel outChannel=out.getChannel();
                long size=inChannel.size();
                //映射内存
                MappedByteBuffer inbuf=inChannel.map(MapMode.READ_ONLY, 0, size);
                MappedByteBuffer outbuf=outChannel.map(MapMode.READ_WRITE, 0, size);
                //buf.flip();
                for(int i=0;i<size;i++){
                    byte b=inbuf.get(i);
                    outbuf.put(i,b);
                }
                
                inChannel.close();
                outChannel.close();
                in.close();
                out.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
  • 相关阅读:
    流程控制值while 循环
    编程语言和变量
    计算机1&操作系统硬件
    使用 Cygwin 在 Windows 中使用 Linux 命令
    windows系统安装mysql及导库
    linux报错 OSError: [Errno 24] Too many open files
    python3报错ModuleNotFoundError: No module named 'Queue'
    mac版本intellij idea默认快捷键
    mysql初设密码及允许远程访问
    PyCharm 图标 c、m、F、f、v、p 分别代表什么含义?
  • 原文地址:https://www.cnblogs.com/shenhainixin/p/5123878.html
Copyright © 2011-2022 走看看