幾種Java讀寫數據的流性能對比


  近來,在做服務器后台處理數據的時候,需要用到Java自帶的幾種流對數據進行讀寫,初始時沒怎么在意,就隨便用了一個,結果發現性能上並不盡如人意。於是對幾種常用的流做了個小小的性能測試。測試代碼如下:

  1     public static int FileOutputStreamTime = 0;
  2     public static int BufferedOutputStreamTime = 0;
  3     public static int FileWriterTime = 0;
  4     public static int FileInputStreamTime = 0;
  5     public static int BufferedInputStreamTime = 0;
  6     public static int FileReaderTime = 0;
  7     
  8     public static void write(String filePath, String content){
  9         FileOutputStream out = null;
 10         FileOutputStream outStr = null;
 11         BufferedOutputStream buf = null;
 12         FileWriter fw = null;
 13         File f = new File(filePath);
 14         
 15         try {
 16             //Test FileOutputStream
 17             long begin1 = System.currentTimeMillis();            
 18             out = new FileOutputStream(f);
 19             out.write(content.getBytes());
 20             out.close();
 21             long end1 = System.currentTimeMillis();
 22             FileOutputStreamTime += end1 - begin1;
 23 
 24             //Test BufferedOutputStream
 25             long begin2 = System.currentTimeMillis();
 26             outStr = new FileOutputStream(f);
 27             buf = new BufferedOutputStream(outStr);
 28             buf.write(content.getBytes());
 29             buf.flush();
 30             buf.close();
 31             long end2 = System.currentTimeMillis();
 32             BufferedOutputStreamTime += end2 - begin2;
 33 
 34             //Test FileWriter
 35             long begin3 = System.currentTimeMillis();
 36             // the second parameter "true",Whether or not a file will be covered
 37             // or appended.
 38             fw = new FileWriter(f);
 39             // fw = new FileWriter("d:/test/testwrite/add2.txt",true);
 40             fw.write(content);
 41             fw.close();
 42             long end3 = System.currentTimeMillis();
 43             FileWriterTime += end3 - begin3;
 44         } catch (Exception e) {
 45             e.printStackTrace();
 46         } finally {
 47             try {
 48                 fw.close();
 49                 buf.close();
 50                 outStr.close();
 51                 out.close();
 52             } catch (Exception e) {
 53                 e.printStackTrace();
 54             }
 55         }
 56     }
 57     
 58     public static void read(String filePath){
 59         FileInputStream in = null;
 60         BufferedInputStream buf = null;
 61         FileReader reader = null;
 62         BufferedReader br = null;
 63         StringBuffer sb = new StringBuffer();
 64         
 65         try {
 66             //Test FileInputStream
 67             long begin1 = System.currentTimeMillis();
 68             File f = new File(filePath);
 69             in = new FileInputStream(f);
 70             int len1 = 512;
 71             byte[] bytes1 = new byte[len1];
 72             
 73             while ((len1 = in.read(bytes1, 0, len1)) != -1) {
 74                 if(len1 < 512){
 75                     byte[] tmpBuf = new byte[len1];
 76                     System.arraycopy(bytes1, 0, tmpBuf, 0, len1);                
 77                     sb.append(new String(tmpBuf));
 78                     tmpBuf = null;
 79                 }else{
 80                     sb.append(new String(bytes1));
 81                 }
 82             }
 83 
 84             in.close();
 85             long end1 = System.currentTimeMillis();
 86             FileInputStreamTime += end1 - begin1;
 87             
 88             //Test BufferedInputStream
 89             long begin2 = System.currentTimeMillis();
 90             int len2 = 512;
 91             byte[] bytes2 = new byte[len2];
 92             buf = new BufferedInputStream(new FileInputStream(f));
 93             while ((len2 = buf.read(bytes2, 0, len2)) != -1) {
 94                 if(len2 < 512){
 95                     byte[] tmpBuf = new byte[len2];
 96                     System.arraycopy(bytes2, 0, tmpBuf, 0, len2);                
 97                     sb.append(new String(tmpBuf));
 98                     tmpBuf = null;
 99                 }else{
100                     sb.append(new String(bytes2));
101                 }
102             }
103 
104             buf.close();
105             long end2 = System.currentTimeMillis();
106             BufferedInputStreamTime += end2 - begin2;
107             
108             //Test FileReader
109             long begin3 = System.currentTimeMillis();
110             reader = new FileReader(f);
111             br = new BufferedReader(reader);
112             String str;
113             while ((str = br.readLine()) != null) {
114                 sb.append(str);
115             }
116             br.close();
117             reader.close();
118             long end3 = System.currentTimeMillis();
119             FileReaderTime += end3 - begin3;
120 
121         } catch (Exception e) {
122             e.printStackTrace();
123         } finally {
124             try {
125                 br.close();
126                 reader.close();
127                 in.close();
128                 buf.close();
129             } catch (Exception e) {
130                 e.printStackTrace();
131             }
132         }
133     }

  測試時,分別對不同大小的數據做500次同樣的操作,取得的平均耗時如下:

不同流耗時對比(ms)
  10K 100K 200K 400K
FileOutputStream 0.496 0.794 1.078 1.602
BufferedOutputStream 0.386 0.684 0.878 1.246
FileWriter 0.586 0.996 1.3 1.946
FileInputStream 0.158 0.544 0.984 1.876
BufferedInputStream 0.152 0.396 0.668 1.068
FileReader 0.152 0.608 1.254 2.19

  通過測試,可以發現,就寫數據而言,BufferedOutputStream耗時是最短的,而性能FileWriter最差;讀數據方面,BufferedInputStream性能最好,而FileReader性能最差勁。所以,以后在涉及到流的讀寫方面時,要注意一下了~

  FileOutputStream 用於寫入諸如圖像數據之類的原始字節的流。要寫入字符流,請考慮使用 FileWriter。

  BufferedOutputStream的數據成員buf是一個位數組,默認為512字節。當使用write()方法寫入數據時,實際上會先將數據寫至buf中,當buf已滿時才會實現給定的OutputStream對象的write()方法,將buf數據寫至目的地,而不是每次都對目的地作寫入的動作。BufferedInputStream也是類似。

  另外,有時只是要存儲一個對象的成員數據,而不是整個對象的信息,成員數據的類型假設都是Java的基本數據類型,這樣的需求不必要使用到與Object輸入、輸出相關的流對象,可以使用DataInputStream、DataOutputStream來寫入或讀出數據。在從文件中讀出數據時,不用費心地自行判斷讀入字符串時或讀入int類型時何時該停止,使用對應的readUTF()或readInt()方法就可以正確地讀入完整類型數據。

  在Java程序執行的過程中,很多數據都是以對象的方式存在於內存中。有時會希望直接將內存中整個對象存儲至文件,而不是只存儲對象中的某些基本類型成員信息,而在下一次程序運行時,希望可以從文件中讀出數據並還原為對象。這時可以使用java.io.ObjectInputStream和java.io.ObjectOutputStream來進行這項工作。

  ByteArrayInputStream可以將一個數組當作流輸入的來源,而ByteArrayOutputStream則可以將一個位數組當作流輸出的目的地。在這里舉一個簡單的文件位編輯程序作為例子,您可以打開一個簡單的文本文件,其中有簡單的A、B、C、D、E、F、G等字符,在讀取文件之后,可以直接以程序來指定文件中位的位置來修改所指定的字符。作法是將文件讀入數組中,指定數組索引修改元素,然后重新將數組存回文件。

  java.io.Reader和java.io.Writer支持Unicode標准字符集(Character Set)(字節流則只支持ISO-Latin-1 8-bit)。在處理流數據時,會根據系統默認的字符編碼來進行字符轉換,Reader和Writer是抽象類,在進行文本文件的字符讀寫時真正會使用其子類,子類通常會重新定義相關的方法。

  如果想要存取的是一個文本文件,可以直接使用java.io.FileReader和java.io.FileWriter類,它們分別繼承自InputStreamReader與OutputStreamWriter。可以直接指定文件名稱或File對象來打開指定的文本文件,並讀入流轉換后的字符,字符的轉換會根據系統默認的編碼(若要指定編碼,則還是使用InputStreamReader與OutputStreamWriter)。

  java.io.BufferedReader與java.io.BufferedWriter類各擁有8192字符的緩沖區。當BufferedReader在讀取文本文件時,會先盡量從文件中讀入字符數據並置入緩沖區,而之后若使用read()方法,會先從緩沖區中進行讀取。如果緩沖區數據不足,才會再從文件中讀取,使用BufferedWriter時,寫入的數據並不會先輸出至目的地,而是先存儲至緩沖區中。如果緩沖區中的數據滿了,才會一次對目的地進行寫出。例如一個文件,通過緩沖區可減少對硬盤的輸入/輸出動作,以提高文件存取的效率。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM