zoukankan      html  css  js  c++  java
  • java-NIO-FileChannel(文件IO)

    Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。

    FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。

    对于文件的复制,平时我们都是使用输入输出流进行操作,利用源文件创建出一个输入流,然后利用目标文件创建出一个输出流,最后将输入流的数据读取写入到输出流中。这样也是可以进行操作的。但是利用fileChannel是很有用的一个方式。它能直接连接输入输出流的文件通道,将数据直接写入到目标文件中去。而且效率更高。
    FileChannel是一个用读写,映射和操作一个文件的通道。除了读写操作之外,还有裁剪特定大小文件truncate(),强制在内存中的数据刷新到硬盘中去force(),对通道上锁lock()等功能。

    他们的使用分别如下面代码:

    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    //读取1024字节内容到byteBuffer钟
    fileChannelInput.read(byteBuffer);

    解释:上面代码首先创建一个1024大小的缓冲对象,然后在输入通道中读取1024大小数据,放入到缓冲对象中。

    byteBuffer.clear();
    byteBuffer.put("需要写入的数据".getBytes()); 
    //类似于flush()函数功能,将buffer里面的数据刷新出去 
    byteBuffer.flip(); 
    //检查是否还有数据未写入 
    while (byteBuffer.hasRemaining()) 
        fileChannelOutput.write(byteBuffer);

    解释:上面的代码是将一段字符串写入到输出文件通道中,因为写入的时候并不保证能一次性写入到文件中,所以需要进行判断是否全部写入,如果没有需要再次调用写入函数操作

    //获取文件通道位置 
    fileChannelInput.position(); 
    fileChannelInput.size(); 
    //截取内容 
    fileChannelInput.truncate(1024); 
    //强制刷新数据到硬盘 
    fileChannelInput.force(true);

    解释:上面的代码是获取文件通道的位置和大小。truncate()方法是截取1024大小的数据,指定长度后面的部分将被删除。以及将数据强制刷新到硬盘中,因为系统会将数据先保存在内存中,不保证数据会立即写入到硬盘中,所以有这个需求,就可以直接强制数据写入内存中。

    使用

    说那么多可能没用,我们还是直接来看看分别使用两种方法进行文件复制的对比。

    首先是普通的输入输出流进行复制文件:

    import org.springframework.util.ResourceUtils;
    
    import java.io.*;
    
    /**
     * 普通的文件复制
     */
    public class FileCopyForNomal {
        public void fileCopy(File fromFile,File toFile){
            InputStream inputStream = null;
            OutputStream outputStream = null;
    
            try {
                inputStream = new BufferedInputStream(new FileInputStream(fromFile));
                outputStream = new BufferedOutputStream(new FileOutputStream(toFile,true));//追加
                byte [] bytes = new byte[1024];
                int i;
                while((i=inputStream.read(bytes)) != -1){
                    outputStream.write(bytes,0,i);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(inputStream!=null){
                        inputStream.close();
                    }if(outputStream!=null){
                        outputStream.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws FileNotFoundException {
            String from = ResourceUtils.getFile("classpath:a.txt").getPath();//这边文件是在target下
            System.out.println(from);
            String to = ResourceUtils.getFile("classpath:b.txt").getPath();//这边文件是在target下
            System.out.println(to);
            File fromFile = new File(from);
            File toFile = new File(to);
    
            Long startTime = System.currentTimeMillis();
            new FileCopyForNomal().fileCopy(fromFile,toFile);
            Long endTime = System.currentTimeMillis();
            System.out.println(endTime-startTime);
        }
    }

    结果:

    G:idea_workspaceiofilechannel	argetclassesa.txt
    G:idea_workspaceiofilechannel	argetclasses.txt
    48

    下面再看一下利用fileChannel进行文件的复制操作。

    import org.springframework.util.ResourceUtils;
    
    import java.io.*;
    import java.nio.channels.FileChannel;
    
    /**
     * 通道文件复制
     */
    public class FileCopyForChannel {
        public void fileCopy(File fromFile, File toFile){
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;
            FileChannel fileChannelInput = null;
            FileChannel fileChannelOutput = null;
            try {
                fileInputStream = new FileInputStream(fromFile);
                fileOutputStream = new FileOutputStream(toFile);
                //得到fileInputStream的文件通道
                fileChannelInput = fileInputStream.getChannel();
                //得到fileOutputStream的文件通道
                fileChannelOutput = fileOutputStream.getChannel();
                //将fileChannelInput通道的数据,写入到fileOutputStream中
                fileChannelInput.transferTo(0,fileChannelInput.size(),fileChannelOutput);
            }catch(IOException e){
                e.printStackTrace();
            }finally {
                try {
                    if (fileInputStream != null)
                        fileInputStream.close();
                    if (fileChannelInput != null)
                        fileChannelInput.close();
                    if (fileOutputStream != null)
                        fileOutputStream.close();
                    if (fileChannelOutput != null)
                        fileChannelOutput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws FileNotFoundException {
            String from = ResourceUtils.getFile("classpath:a.txt").getPath();//这边文件是在target下
            System.out.println(from);
            String to = ResourceUtils.getFile("classpath:b.txt").getPath();//这边文件是在target下
            System.out.println(to);
            File fromFile = new File(from);
            File toFile = new File(to);
    
            Long startTime = System.currentTimeMillis();
            new FileCopyForChannel().fileCopy(fromFile,toFile);
            Long endTime = System.currentTimeMillis();
            System.out.println(endTime-startTime);
        }
    }

    结果:

    G:idea_workspaceiofilechannel	argetclassesa.txt
    G:idea_workspaceiofilechannel	argetclasses.txt
    22

    运行代码之后,复制一个文件,对比两种复制方法,发现利用filechannel使用的时间比普通的读取输入时间缩短了将近一半。尤其是在进行大文件复制的时候,filechannel显得更加有优势。

    总结

    这里我们了解了FileChannel类,知道了它所具有的特点和功能,那么我们就可以好好的使用它了。尤其是在我们复制文件的时候,可以更好的利用这个类,可以提高效率,也可以防止出现oom等其它情况。

    源码地址:https://github.com/qjm201000/io_nio_filechannel.git

  • 相关阅读:
    《Geometric Deep Learning综述介绍》
    《和想象不太一样的'Graph Neural Network + Zero Shot'》
    《几何深度学习前沿》
    《【Paper Live】滴滴出行-探索资源约束的Contextual Bandits问题 & KDD Cup滴滴出行比赛解读>
    《PDP: 解决约束满足问题的神经网络架构 | 刘晶 | 集智俱乐部图网络论文读书会20190819》
    《NeuroSAT: Learning a SAT Solver from Single-Bit Supervision》
    《OR Talk NO.5 | Facebook 田渊栋:用深度(强化)学习为组合优化寻找更好的启发式搜索策略》
    《OR Talk NO.15 | 在业界实验室做AI设计师是一种什么体验?》
    超级跳马 —— 矩阵快速幂优化DP
    图SLAM:Noob的同时本地化和映射指南
  • 原文地址:https://www.cnblogs.com/qjm201000/p/10287393.html
Copyright © 2011-2022 走看看