java-IO操作性能對比

jopen 10年前發布 | 36K 次閱讀 Java Java開發

在軟件系統中,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;  
    }  

}  </pre></span><span style="font-size:18px;">運行結果:<pre class="brush:java; toolbar: true; auto-links: false;">    io stream copy:384  
buffered stream copy:125  
nio stream copy:12  
nio memory stream copy:10  </pre></span>結論分析:<p></p>

最普通的InputStream操作耗時較長,增加了緩存后速度增加了,用了nio和內存映射訪問文件,速度最快。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!