zoukankan      html  css  js  c++  java
  • FileChannel原理

     官方对Channel的解释

     

    (一个用于输入/输出操作的连接。通道表示对实体的开放连接,如硬件设备、文件、网络套接字或能够执行一个或多个不同的输入/输出操作的程序组件,例如读取或写入。)

    Thanking In Java中的描述

    Channel是对I/O操作的封装。

    FileChannel配合着ByteBuffer,将读写的数据缓存到内存中,然后以批量/缓存的方式read/write,省去了非批量操作时的重复中间操作,操纵大文件时可以显著提高效率(和Stream以byte数组方式有什么区别?经过测试,效率上几乎无区别)。

    不过对于运行在容器中的应用需要考虑GC,而ByteBuffer可以使用直接内存(系统内存)(allocateDirect),使用后无需jvm回收。

    ByteBuffer还有一个子类MappedByteBuffer可以直接将文件映射到操作系统的虚拟内存,读写文件速度会更快,参考https://www.cnblogs.com/lyftest/p/6564282.html。

    FileChannel和Stream的使用方式和效率对比代码

      1 import java.io.*;
      2 import java.nio.ByteBuffer;
      3 import java.nio.channels.FileChannel;
      4 import java.time.Duration;
      5 import java.time.Instant;
      6 
      7 public class FileChannelTest {
      8 
      9     public static void main(String[] args) {
     10         // 4GB的数据
     11         File sourceFile = new File("d://dd.iso");
     12         File targetFile = new File("d://ee.iso");
     13         targetFile.deleteOnExit();
     14         try {
     15             targetFile.createNewFile();
     16         } catch (IOException e) {
     17             e.printStackTrace();
     18         }
     19 
     20         // stream方式
     21         FileChannelTest.copyFileByStream(sourceFile, targetFile);
     22 
     23         // channel方式
     24 //        FileChannelTest.copyFileByFileChannel(sourceFile, targetFile);
     25     }
     26 
     27     /**
     28      * channel方式
     29      *
     30      * @param sourceFile
     31      * @param targetFile
     32      */
     33     public static void copyFileByFileChannel(File sourceFile, File targetFile) {
     34         Instant begin = Instant.now();
     35 
     36         RandomAccessFile randomAccessSourceFile;
     37         RandomAccessFile randomAccessTargetFile;
     38         try {
     39             // 构造RandomAccessFile,用于获取FileChannel
     40             randomAccessSourceFile = new RandomAccessFile(sourceFile, "r");
     41             randomAccessTargetFile = new RandomAccessFile(targetFile, "rw");
     42         } catch (FileNotFoundException e) {
     43             e.printStackTrace();
     44             return;
     45         }
     46 
     47         FileChannel sourceFileChannel = randomAccessSourceFile.getChannel();
     48         FileChannel targetFileChannel = randomAccessTargetFile.getChannel();
     49 
     50         // 分配1MB的缓存空间
     51         ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
     52         try {
     53             while (sourceFileChannel.read(byteBuffer) != -1) {
     54                 byteBuffer.flip();
     55                 targetFileChannel.write(byteBuffer);
     56                 byteBuffer.clear();
     57             }
     58         } catch (IOException e) {
     59             e.printStackTrace();
     60         } finally {
     61             try {
     62                 sourceFileChannel.close();
     63             } catch (IOException e) {
     64                 e.printStackTrace();
     65             }
     66             try {
     67                 targetFileChannel.close();
     68             } catch (IOException e) {
     69                 e.printStackTrace();
     70             }
     71         }
     72 
     73         System.out.println("total spent " + Duration.between(begin, Instant.now()).toMillis());
     74     }
     75 
     76     /**
     77      * stream方式
     78      *
     79      * @param sourceFile
     80      * @param targetFile
     81      */
     82     public static void copyFileByStream(File sourceFile, File targetFile) {
     83         Instant begin = Instant.now();
     84 
     85         FileInputStream fis;
     86         FileOutputStream fos;
     87         try {
     88             fis = new FileInputStream(sourceFile);
     89             fos = new FileOutputStream(targetFile);
     90         } catch (FileNotFoundException e) {
     91             e.printStackTrace();
     92             return;
     93         }
     94         // 使用byte数组读取方式,缓存1MB数据
     95         byte[] readed = new byte[1024 * 1024];
     96         try {
     97             while (fis.read(readed) != -1) {
     98                 fos.write(readed);
     99             }
    100         } catch (IOException e) {
    101             e.printStackTrace();
    102         } finally {
    103             try {
    104                 fos.close();
    105             } catch (IOException e) {
    106                 e.printStackTrace();
    107             }
    108             try {
    109                 fis.close();
    110             } catch (IOException e) {
    111                 e.printStackTrace();
    112             }
    113         }
    114 
    115         System.out.println("total spent " + Duration.between(begin, Instant.now()).toMillis());
    116     }
    117 }
  • 相关阅读:
    小白日记41:kali渗透测试之Web渗透-SQL手工注入(三)-猜测列名、表名、库名、字段内容,数据库写入
    Python实现百度贴吧自动顶贴机
    回文自动机简述
    计算几何基本知识整理
    考试题Speed
    [ZOJ 2112] [lg2617] Dynamic Rankings
    后缀数组(Suffix Arrary)
    莫比乌斯函数与莫比乌斯反演
    题解 洛谷 P3369 【【模板】普通平衡树】
    EXCRT(扩展中国剩余定理)
  • 原文地址:https://www.cnblogs.com/zhya/p/9640016.html
Copyright © 2011-2022 走看看