Java NIO 读取文件

 2022-07-27
原文作者:会改bug的程序员 原文地址:https://blog.csdn.net/qq_21083291/article/details/119680301

一、JavaNIO读取文件

1、使用缓冲区,非直接缓冲区读写文件

     @Test
     public void test3() {
             FileInputStream fis = null;
             FileOutputStream fos = null;
             FileChannel fisChannel = null;
             FileChannel fosChannel = null;
             try {
                 // ServerSocketChannel open = ServerSocketChannel.open();
                 fis = new FileInputStream("1.jpg");
                 fos = new FileOutputStream("2.jpg");
                 fisChannel = fis.getChannel();
                 fosChannel = fos.getChannel();
    
                 // 分配指定大小的缓冲区
                 ByteBuffer buf = ByteBuffer.allocateDirect(1024);
                 // 将通道中的数据存取缓冲区
                 while (fisChannel.read(buf) != -1) {
                     // 读取信息
                     buf.flip();
                     fosChannel.write(buf);
    
                     buf.clear();
    
                 }
             } catch (FileNotFoundException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             } finally {
                 if (fos != null) {
                     try {
                         fos.close();
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
                 if (fis != null) {
                     try {
                         fis.close();
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
                 if (fosChannel != null) {
                     try {
                         fosChannel.close();
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
                 if (fisChannel != null) {
                     try {
                         fisChannel.close();
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
             }
        }

2、使用直接缓冲区读写文件,速度快,不建议使用,占内存

    @Test
        public void test4() throws IOException {
    
             // 读模式
             FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
             // StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
             FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
                     StandardOpenOption.CREATE);
             // 内存映射文件和ByteBuffer.allocateDirect(1024);直接获取缓冲区一模一样
             // 缓存区目前在物理内存中,直接缓冲区只有ByteBuffer支持
             MappedByteBuffer map = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
             MappedByteBuffer map2 = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
    
             // 直接操作缓冲区
             byte[] bs = new byte[map.limit()];
             map.get(bs);
             map2.put(bs);
    
        }      

3、分散与读取,将通道中的内容分散到缓冲区中

    /**
         * 分散与读取,将通道中的内容分散到缓冲区中
         *
         * @throws FileNotFoundException
         */
        @Test
        public void test6() throws Exception {
             // 分散读取
             RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
             // 获取通道
             FileChannel channel = raf.getChannel();
    
             // 分配指定大小缓冲区
             ByteBuffer allocate = ByteBuffer.allocate(100);
             ByteBuffer allocate2 = ByteBuffer.allocate(1000);
             // 分散读取
             ByteBuffer[] bio = { allocate, allocate2 };
             channel.read(bio);
             for (ByteBuffer byteBuffer : bio) {
                 // 改编读模式
                 byteBuffer.flip();
             }
             // 将缓冲区转换为数组,从第0个转换到limit
             System.out.println(new String(bio[0].array(), 0, bio[0].limit()));
            System.out.println("======================");
             System.out.println(new String(bio[0].array(), 0, bio[1].limit()));
    
             // 聚集写入
             RandomAccessFile rsf = new RandomAccessFile("2.txt", "rw");
             FileChannel channel2 = rsf.getChannel();
    
             channel2.write(bio);
    
        }
    
        /**
         * 通道之间传输数据,直接缓冲区复制文件
         *
         * @throws IOException
         */
        @Test
        public void test5() throws IOException {
             // 读模式
             FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
             // StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
             FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
                     StandardOpenOption.CREATE);
             // 从哪到哪去
             inChannel.transferTo(0, inChannel.size(), outChannel);
             outChannel.transferFrom(inChannel, 0, inChannel.size());
             inChannel.close();
             outChannel.close();
        }
    
        /**
         * 直接缓冲区进行文件费复制
         *
         * @throws IOException
         */
        @Test
        public void test4() throws IOException {
    
             // 读模式
             FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
             // StandardOpenOption.CREATE没有就创建,有就覆盖,StandardOpenOption.CREATE_NEW有就报错
             FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ,
                     StandardOpenOption.CREATE);
             // 内存映射文件和ByteBuffer.allocateDirect(1024);直接获取缓冲区一模一样
             // 缓存区目前在物理内存中,直接缓冲区只有ByteBuffer支持
             MappedByteBuffer map = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
             MappedByteBuffer map2 = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
    
             // 直接操作缓冲区
             byte[] bs = new byte[map.limit()];
             map.get(bs);
             map2.put(bs);
    
        }
    
        /**
         * 非直接缓冲区实现文件复制
         */
    
        @Test
        public void test3() {
    
             FileInputStream fis = null;
             FileOutputStream fos = null;
             FileChannel fisChannel = null;
             FileChannel fosChannel = null;
             try {
                 // ServerSocketChannel open = ServerSocketChannel.open();
                 fis = new FileInputStream("1.jpg");
                 fos = new FileOutputStream("2.jpg");
                 fisChannel = fis.getChannel();
                 fosChannel = fos.getChannel();
    
                 // 分配指定大小的缓冲区
                 ByteBuffer buf = ByteBuffer.allocateDirect(1024);
                 // 将通道中的数据存取缓冲区
                 while (fisChannel.read(buf) != -1) {
                     // 读取信息
                     buf.flip();
                     fosChannel.write(buf);
    
                     buf.clear();
    
                 }
             } catch (FileNotFoundException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             } finally {
                 try {
                     if (fos != null) {
                         fos.close();
    
                     }
                     if (fis != null) {
                         fis.close();
    
                     }
                     if (fosChannel != null) {
                         fosChannel.close();
                     }
                     if (fisChannel != null) {
                         fisChannel.close();
                     }
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
    
        }
    
    
    
        @Test
       public void test1() {
    
             ByteBuffer buf = ByteBuffer.allocate(1024);
             // 可以操作数据的位置
             System.out.println(buf.position());
             // 可以操作数据的大小
    
             System.out.println(buf.limit());
             // 最大储存容量
             System.out.println(buf.capacity());
             String string = "asd";
             buf.put(string.getBytes());
             // 切换到读取数据模式
             buf.flip();
             // 可重复读数据
             buf.rewind();
             buf.clear();
             // 标记位置
             buf.mark();
             // 回复到标记位置
             buf.reset();
             // 判断缓冲区中是否还有缓冲数据,如果有
             if (buf.hasRemaining()) {
                 // 获取缓冲区中可以操作的数量
                 System.out.println(buf.remaining());
             }
    
        }