java-IO操作性能对比

jopen 11年前

在软件系统中,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();                System.out.println("io stream copy:" + ioStreamTime1);                        long ioStreamTime2 = bufferedStreamCopy();                System.out.println("buffered stream copy:" + ioStreamTime2);                        long ioStreamTime3 = nioStreamCopy();                System.out.println("nio stream copy:" + ioStreamTime3);                                long ioStreamTime4 = nioMemoryStreamCopy();                System.out.println("nio memory stream copy:" + ioStreamTime4);            }                    /**            * 普通文件流读写            *             * @return 操作的时间            */            private static long ioStreamCopy() {                long costTime = -1;                FileInputStream is = null;                FileOutputStream os = null;                try {                    long startTime = System.currentTimeMillis();                    is = new FileInputStream(INPUT_FILE_PATH);                    os = new FileOutputStream(OUTPUT_FILE_PATH);                    int read = is.read();                    while (read != -1) {                        os.write(read);                        read = is.read();                    }                    long endTime = System.currentTimeMillis();                    costTime = endTime - startTime;                }                catch (FileNotFoundException e) {                    e.printStackTrace();                }                catch (IOException e) {                    e.printStackTrace();                }                finally {                    try {                        if (is != null) {                            is.close();                        }                        if (os != null) {                            os.close();                        }                    }                    catch (IOException e) {                        e.printStackTrace();                    }                }                return costTime;            }                    /**            * 加入缓存的文件流读写, Reader默认实现缓存,只能读取字符文件,无法准确读取字节文件如图片视频等            *             * @return 操作的时间            */            private static long bufferedStreamCopy() {                long costTime = -1;                FileReader reader = null;                FileWriter writer = null;                try {                    long startTime = System.currentTimeMillis();                    reader = new FileReader(INPUT_FILE_PATH);                    writer = new FileWriter(OUTPUT_FILE_PATH);                    int read = -1;                    while ((read = reader.read()) != -1) {                        writer.write(read);                    }                    writer.flush();                    long endTime = System.currentTimeMillis();                    costTime = endTime - startTime;                }                catch (FileNotFoundException e) {                    e.printStackTrace();                }                catch (IOException e) {                    e.printStackTrace();                }                finally {                    try {                        if (reader != null) {                            reader.close();                        }                        if (writer != null) {                            writer.close();                        }                    }                    catch (IOException e) {                        e.printStackTrace();                    }                }                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 = System.currentTimeMillis();                    is = new FileInputStream(INPUT_FILE_PATH);                    os = new FileOutputStream(OUTPUT_FILE_PATH);                    fi = is.getChannel();                    fo = os.getChannel();                    ByteBuffer buffer = ByteBuffer.allocate(1024);                    while (true) {                        buffer.clear();                        int read = fi.read(buffer);                        if (read == -1) {                            break;                        }                        buffer.flip();                        fo.write(buffer);                    }                    long endTime = System.currentTimeMillis();                    costTime = endTime - startTime;                }                catch (FileNotFoundException e) {                    e.printStackTrace();                }                catch (IOException e) {                    e.printStackTrace();                }                finally {                    try {                        if (fi != null) {                            fi.close();                        }                        if (fo != null) {                            fo.close();                        }                        if (is != null) {                            is.close();                        }                        if (os != null) {                            os.close();                        }                    }                    catch (IOException e) {                        e.printStackTrace();                    }                }                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 = System.currentTimeMillis();                    is = new FileInputStream(INPUT_FILE_PATH);                    os = new RandomAccessFile(OUTPUT_FILE_PATH, "rw");                    fi = is.getChannel();                    fo = os.getChannel();                    IntBuffer iIb=fi.map(FileChannel.MapMode.READ_ONLY, 0, fi.size()).asIntBuffer();                    IntBuffer oIb = fo.map(FileChannel.MapMode.READ_WRITE, 0, fo.size()).asIntBuffer();                    while(iIb.hasRemaining()){                        int read = iIb.get();                        oIb.put(read);                    }                    long endTime = System.currentTimeMillis();                    costTime = endTime - startTime;                }                catch (FileNotFoundException e) {                    e.printStackTrace();                }                catch (IOException e) {                    e.printStackTrace();                }                finally {                    try {                        if (fi != null) {                            fi.close();                        }                        if (fo != null) {                            fo.close();                        }                        if (is != null) {                            is.close();                        }                        if (os != null) {                            os.close();                        }                    }                    catch (IOException e) {                        e.printStackTrace();                    }                }                return costTime;            }                }  
运行结果:
    io stream copy:384        buffered stream copy:125        nio stream copy:12        nio memory stream copy:10  
结论分析:

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