java-IO操作性能对比

时间:2025-02-10 19:44:27

在软件系统中,IO速度比内存速度慢,IO读写在很多情况下会是系统的瓶颈。

在java标准IO操作中,InputStream和OutputStream提供基于流的IO操作,以字节为处理单位;Reader和Writer实现了Buffered缓存,以字符为处理单位。

从Java1.4开始,增加NIO(New IO),增加缓存Buffer和通道Channel,以块为处理单位,是双向通道(可读可写,类似RandomAccessFile),支持锁和内存映射文件访问接口,大大提升了IO速度。

以下例子简单测试常见IO操作的性能速度。


/**
 * 测试不同io操作速度
 * 
 * @author peter_wang
 * @create-time 2014-6-4 下午12:52:48
 */
public class SpeedTest {
    private static final String INPUT_FILE_PATH = "io_speed.txt";
    private static final String OUTPUT_FILE_PATH = "io_speed_copy.txt";

    /**
     * @param args
     */
    public static void main(String[] args) {
        long ioStreamTime1 = ioStreamCopy();
        ("io stream copy:" + ioStreamTime1);

        long ioStreamTime2 = bufferedStreamCopy();
        ("buffered stream copy:" + ioStreamTime2);

        long ioStreamTime3 = nioStreamCopy();
        ("nio stream copy:" + ioStreamTime3);
        
        long ioStreamTime4 = nioMemoryStreamCopy();
        ("nio memory stream copy:" + ioStreamTime4);
    }

    /**
     * 普通文件流读写
     * 
     * @return 操作的时间
     */
    private static long ioStreamCopy() {
        long costTime = -1;
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            long startTime = ();
            is = new FileInputStream(INPUT_FILE_PATH);
            os = new FileOutputStream(OUTPUT_FILE_PATH);
            int read = ();
            while (read != -1) {
                (read);
                read = ();
            }
            long endTime = ();
            costTime = endTime - startTime;
        }
        catch (FileNotFoundException e) {
            ();
        }
        catch (IOException e) {
            ();
        }
        finally {
            try {
                if (is != null) {
                    ();
                }
                if (os != null) {
                    ();
                }
            }
            catch (IOException e) {
                ();
            }
        }
        return costTime;
    }

    /**
     * 加入缓存的文件流读写, Reader默认实现缓存,只能读取字符文件,无法准确读取字节文件如图片视频等
     * 
     * @return 操作的时间
     */
    private static long bufferedStreamCopy() {
        long costTime = -1;
        FileReader reader = null;
        FileWriter writer = null;
        try {
            long startTime = ();
            reader = new FileReader(INPUT_FILE_PATH);
            writer = new FileWriter(OUTPUT_FILE_PATH);
            int read = -1;
            while ((read = ()) != -1) {
                (read);
            }
            ();
            long endTime = ();
            costTime = endTime - startTime;
        }
        catch (FileNotFoundException e) {
            ();
        }
        catch (IOException e) {
            ();
        }
        finally {
            try {
                if (reader != null) {
                    ();
                }
                if (writer != null) {
                    ();
                }
            }
            catch (IOException e) {
                ();
            }
        }
        return costTime;
    }

    /**
     * nio操作数据流
     * 
     * @return 操作的时间
     */
    private static long nioStreamCopy() {
        long costTime = -1;
        FileInputStream is = null;
        FileOutputStream os = null;
        FileChannel fi = null;
        FileChannel fo = null;
        try {
            long startTime = ();
            is = new FileInputStream(INPUT_FILE_PATH);
            os = new FileOutputStream(OUTPUT_FILE_PATH);
            fi = ();
            fo = ();
            ByteBuffer buffer = (1024);
            while (true) {
                ();
                int read = (buffer);
                if (read == -1) {
                    break;
                }
                ();
                (buffer);
            }
            long endTime = ();
            costTime = endTime - startTime;
        }
        catch (FileNotFoundException e) {
            ();
        }
        catch (IOException e) {
            ();
        }
        finally {
            try {
                if (fi != null) {
                    ();
                }
                if (fo != null) {
                    ();
                }
                if (is != null) {
                    ();
                }
                if (os != null) {
                    ();
                }
            }
            catch (IOException e) {
                ();
            }
        }
        return costTime;
    }

    /**
     * nio内存映射操作数据流
     * 
     * @return 操作的时间
     */
    private static long nioMemoryStreamCopy() {
        long costTime = -1;
        FileInputStream is = null;
        //映射文件输出必须用RandomAccessFile
        RandomAccessFile os = null;
        FileChannel fi = null;
        FileChannel fo = null;
        try {
            long startTime = ();
            is = new FileInputStream(INPUT_FILE_PATH);
            os = new RandomAccessFile(OUTPUT_FILE_PATH, "rw");
            fi = ();
            fo = ();
            IntBuffer iIb=(.READ_ONLY, 0, ()).asIntBuffer();
            IntBuffer oIb = (.READ_WRITE, 0, ()).asIntBuffer();
            while(()){
                int read = ();
                (read);
            }
            long endTime = ();
            costTime = endTime - startTime;
        }
        catch (FileNotFoundException e) {
            ();
        }
        catch (IOException e) {
            ();
        }
        finally {
            try {
                if (fi != null) {
                    ();
                }
                if (fo != null) {
                    ();
                }
                if (is != null) {
                    ();
                }
                if (os != null) {
                    ();
                }
            }
            catch (IOException e) {
                ();
            }
        }
        return costTime;
    }

}
运行结果:

io stream copy:384
buffered stream copy:125
nio stream copy:12
nio memory stream copy:10

结论分析:

最普通的InputStream操作耗时较长,增加了缓存后速度增加了,用了nio和内存映射访问文件,速度最快。