首页 > 技术文章 > java IO性能对比----read文件

aksdenjoy 2017-02-14 09:05 原文

本次对比内容为:(jdk1.8)

fileInputStream:最基本的文件读取(带自己声明的缓冲区)

dataInputStream:字节读取,在《java编程思想》一书中描述为使用最多的读取文件方式(带自己声明的缓冲区)

bufferedInputStream:带缓冲的读取方式(带自己声明的缓冲区)

dataInputStream(bufferedInputStream):组合后的读取方式(带自己声明的缓冲区)

bufferedReader:字符读取方式

channel:nio中的新的读取方式

map:内存映射文件

(说明:本次对比都有缓存参与,不对比无缓存的情况,因为无缓存情况下的任意方式的读性能远远落后于有缓存的方式,因此不在此对比)

对同一文件的读取:文件为大小为:a)847 MB (888,888,890 字节) b)75.2 MB (78,888,890 字节) c) 6.56 MB (6,888,890 字节) d) 575 KB (588,890 字节) 

 

package javaIO;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created by EnjoyD on 2016/12/20.
 */
public class IO {
    private static String filepath="." + File.separator +"testIO.txt";
    private abstract static class Tester{
        private String name;
        Tester(String name){
            this.name=name;
        }
        private void runTest(){
            try {
                long start=System.currentTimeMillis();
                test();
                long offset=System.currentTimeMillis()-start;
                System.out.println(this.name+":"+offset);
            }catch (Exception e){
                System.err.println("err");
                e.printStackTrace();
            }
        }
        public abstract void test() throws IOException;
    }
    private static Tester [] testers={
            new Tester("fileInputStream") {
                @Override
                public void test() throws IOException {
                    FileInputStream f=new FileInputStream(filepath);
                    {
                        int read;
                        byte []b=new byte[1024];
                        while((read=f.read(b,0,1024))!=-1)
                            for (int i=0;i<1024;i++) {
                                byte tem = b[i];
                            }
                    }
                    f.close();
                }
            },
            new Tester("dataInputStream") {
                @Override
                public void test() throws IOException {
                    DataInputStream d=new DataInputStream(new FileInputStream(filepath));
                    {
                        int read;
                        byte []b=new byte[1024];
                        while ((read=d.read(b,0,1024))!=-1)
                            for (int i=0;i<1024;i++) {
                                byte tem = b[i];
                            }
                    }
                    d.close();
                }
            },
            new Tester("bufferedInputStream") {
                @Override
                public void test() throws IOException{
                    BufferedInputStream b=new BufferedInputStream(new FileInputStream(filepath),1024);
                    {
                        int read;
                        byte [] by=new byte[1024];
                        while((read=b.read(by,0,1024))!=-1)
                            for (int i=0;i<1024;i++) {
                                byte tem = by[i];
                            }
                    }
                    b.close();
                }
            },
            new Tester("datainputStream(buferedinputStream)") {
                @Override
                public void test() throws IOException {
                    DataInputStream d=new DataInputStream(new BufferedInputStream(new FileInputStream(filepath),1024));
                    {
                        int read;
                        byte [] by=new byte[1024];
                        while((read=d.read(by,0,1024))!=-1)
                            for (int i=0;i<1024;i++) {
                                byte tem = by[i];
                            }

                    }
                    d.close();
                }
            },
            new Tester("bufferedReader") {
                @Override
                public void test() throws IOException {
                    Reader f=new BufferedReader(new FileReader(filepath));
                    {
                        int read;
                        while((read=f.read())!=-1);
                    }
                    f.close();
                }
            },
            new Tester("channel") {
                @Override
                public void test() throws IOException {
                    FileChannel fc=new FileInputStream(filepath).getChannel();
                    ByteBuffer buff=ByteBuffer.allocate(1024);
                    while((fc.read(buff)!=-1)){
              buff.flip();
while (buff.hasRemaining()){ buff.get(); } buff.clear(); } fc.close(); } }, new Tester("maped") { @Override public void test() throws IOException { FileChannel fc=new RandomAccessFile(filepath,"rw").getChannel(); ByteBuffer buff=fc.map(FileChannel.MapMode.READ_ONLY,0,fc.size()).asReadOnlyBuffer(); while (buff.hasRemaining()) { buff.get(); } fc.close(); } } }; public static void main(String[] args) { for (Tester t :testers){ t.runTest(); } } }

测试1:847 MB (888,888,890 字节)  单位“豪秒”

 

测试2:75.2 MB (78,888,890 字节) 单位“豪秒”

测试3:6.56 MB (6,888,890 字节) 单位“豪秒”

测试4:575 KB (588,890 字节) 单位“豪秒”

根据这些基本的测试来看,对于大文件读取,在使用了自己声明的1K缓冲区后,前四种方式的读取字节的速度相差不多,并且与最后一种方式----内存映射文件的读取速度相差不多。因此如果需要按字节进行读取,前四种方式皆可,当然如果内存足够大,可以直接使用内存映射文件的方式读取。

 

推荐阅读