java四种文件读写方式及性能比较

测试代码

package com.boot.demo.test.io;

import java.io.*;
import java.lang.reflect.Method;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * @author braska
 * @date 2020/3/19
 **/
public class FileTest {

    public static void fileStream(String sourceFile, String targetFile) {
        File file = new File(targetFile);
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(file)) {
            byte[] bytes = new byte[1024 * 1024];
            int len;
            while ((len = fis.read(bytes)) > 0) {
                fos.write(bytes, 0, len);
            }
        } catch (Exception e) {

        }
    }

    public static void bufferStream(String sourceFile, String targetFile) {
        try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(Paths.get(sourceFile)));
             BufferedOutputStream bos =
                     new BufferedOutputStream(Files.newOutputStream(Paths.get(targetFile),
                             StandardOpenOption.CREATE,
                             StandardOpenOption.TRUNCATE_EXISTING,
                             StandardOpenOption.WRITE))) {
            byte[] bytes = new byte[1024 * 1024];
            int len;
            while ((len = bis.read(bytes)) > 0) {
                bos.write(bytes, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void randomFile(String sourceFile, String targetFile) {
        try (RandomAccessFile read = new RandomAccessFile(sourceFile, "r");
             RandomAccessFile write = new RandomAccessFile(targetFile, "rw")) {
            byte[] bytes = new byte[1024 * 1024];
            int len;
            while ((len = read.read(bytes)) > 0) {
                write.write(bytes, 0, len);
            }
        } catch (Exception e) {

        }
    }

    public static void memoryMap(String sourceFile, String targetFile) {
        try (FileChannel rc = FileChannel.open(Paths.get(sourceFile));
             FileChannel wc = FileChannel.open(Paths.get(targetFile),
                     StandardOpenOption.CREATE,
                     StandardOpenOption.READ,
                     StandardOpenOption.TRUNCATE_EXISTING,
                     StandardOpenOption.WRITE)) {
            long copy = 1L << 30;
            long cur = 0;
            long fileLength = rc.size();
            while (cur < fileLength) {
                MappedByteBuffer rMap = rc.map(FileChannel.MapMode.READ_ONLY, cur, copy);
                MappedByteBuffer wMap = wc.map(FileChannel.MapMode.READ_WRITE, cur, copy);
                for (int i = 0; i < copy; i++) {
                    byte b = rMap.get(i);			//从源文件读取字节
                    wMap.put(i, b);					//把字节写到目标文件中
                }
                System.gc();				//手动调用 GC		<必须的,否则出现异常>
                System.runFinalization();
                cur += copy;
                copy = cur + copy > fileLength ? (fileLength - cur) : copy;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void clean(final MappedByteBuffer buffer) throws Exception {
        if (buffer == null) {
            return;
        }
        buffer.force();
        AccessController.doPrivileged(new PrivilegedAction<Object>() {//Privileged特权
            @Override
            public Object run() {
                try {
                    // System.out.println(buffer.getClass().getName());
                    Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
                    getCleanerMethod.setAccessible(true);
                    sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(buffer, new Object[0]);
                    cleaner.clean();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

    private static String buildFilePath(String path, String fileName, String extension) {
        return String.format("%s%s.%s", path, fileName, extension);
    }

    public static void main(String[] args) {
/*        String path = "F:\\workspace\\demo\\";
        String extension = "hprof";
        // 30M文件
        String sourceFile = buildFilePath(path, "01", extension);*/

/*        String path = "E:\\software\\";
        String extension = "exe";
        // 460M文件
        String sourceFile = buildFilePath(path, "Anaconda3-2019.10-Windows-x86_64", extension);*/

        String path = "E:\\software\\";
        String extension = "zip";
        // 1.47G文件
        String sourceFile = buildFilePath(path, "software", extension);
        String targetFile;
        long start;

/*        targetFile = buildFilePath(path, "target_file_stream", extension);
        start = System.currentTimeMillis();
        FileTest.fileStream(sourceFile, targetFile);
        System.out.println("file stream used time:" + (System.currentTimeMillis() - start));*/

/*        targetFile = buildFilePath(path, "target_buffer_stream", extension);
        start = System.currentTimeMillis();
        FileTest.bufferStream(sourceFile, targetFile);
        System.out.println("buffer stream used time:" + (System.currentTimeMillis() - start));*/

/*        targetFile = buildFilePath(path, "target_random_file", extension);
        start = System.currentTimeMillis();
        FileTest.randomFile(sourceFile, targetFile);
        System.out.println("random file used time:" + (System.currentTimeMillis() - start));*/

        targetFile = buildFilePath(path, "target_memory_map", extension);
        start = System.currentTimeMillis();
        FileTest.memoryMap(sourceFile, targetFile);
        System.out.println("memory map used time:" + (System.currentTimeMillis() - start));
    }
}

测试结果

文件大小 读写方式 耗时
30M 普通文件流 50-60 ms
缓存流 32-35ms
随机文件方式 40-50ms
内存映射文件 50-60ms
461M 普通文件流 1300-2300 ms
缓存流 1700-2000 ms
随机文件方式 1300-3000 ms
内存映射文件 890-1000 ms
1.47G 普通文件流 11s
缓存流 9s
随机文件方式 10s
内存映射文件 1.6s

原文地址:https://www.cnblogs.com/braska/p/12525773.html

时间: 2024-10-08 14:51:00

java四种文件读写方式及性能比较的相关文章

XML的四种解析器原理及性能比较

转自zsq 1.DOM     DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.DOM 是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的.DOM 以及广义的基于树的处理具有几个优点.    首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何时候在树中上下导航,而不

Java IO和Java NIO在文件拷贝上的性能差异分析 (转)

1.       在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取 到用户空间的缓冲区.参看read(byte b[])方法的源码,可知,它会在内部再调用readBytes(b, 0, b.length)方法,而且readBytes(b, 0, b.length)方法是一个native方法(即本地方法),最终通过这个本地方法来发起一次系统调用,即调用系统内核的read()

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

Java四种线程池

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor 时间:2015-10-20 22:37:40      阅读:8762      评论:0      收藏:0      [点我收藏+] 介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异

笔试算法题(53):四种基本排序方法的性能特征(Selection,Insertion,Bubble,Shell)

四种基本算法概述: 基本排序:选择,插入,冒泡,希尔.上述算法适用于小规模文件和特殊文件的排序,并不适合大规模随机排序的文件.前三种算法的执行时间与N2成正比,希尔算法的执行时间与N3/2(或更快)成正比: 前三种算法在平均,最坏情况下都是N2,而且都不需要额外的内存:所以尽管他们的运行时间只相差常数倍,但运行方式不同: 对于已经就序的序列而言,插入排序和冒泡排序的运行时间都是O(N),但是选择排序的时间仍旧是O(N^2): 因为Insertion和Bubble都是相邻项间的比较交换,所以不会出

Pascal、VB、C#、Java四种语法对照表

因为工作原因,自学会了vb后陆续接触了其它语言,在工作中经常需要与各家使用不同语言公司的开发人员做程序对接,初期特别需要一个各种语法的对照比,翻看了网络上已有高人做了整理,自己在他基础上也整理了一下,摘抄如下(最后附上原作,网上也可以找到): 类别 Vb6 & Vb.Net Delphi C# 语法 不区分大小写 不区分大小写 区分大小写 数据类型 数据     关键字    占用字节      类型符 整型          integer 长整型        long 单精度型     

Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

原文:http://www.cnblogs.com/zhujiabin/p/5404771.html 介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stu

Button的四种监听方式

Button按钮设置点击的四种监听方式 注:加粗放大的都是改变的代码 1.使用匿名内部类的形式进行设置 使用匿名内部类的形式,直接将需要设置的onClickListener接口对象初始化,内部的onClick方法会在按钮被点击的时候执行 第一个活动的java代码: 1 package com.sanlian.buttontest; 2 3 import android.content.Intent; 4 import android.support.v7.app.AppCompatActivit

Java四种引用包括强引用,软引用,弱引用,虚引用

Java四种引用包括强引用,软引用,弱引用,虚引用. 强引用: 只要引用存在,垃圾回收器永远不会回收Object obj = new Object();//可直接通过obj取得对应的对象 如obj.equels(new Object());而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式. 软引用: 非必须引用,内存溢出之前进行回收,可以通过以下代码实现Object obj = new Object();S