Java文件操作類效率對比


前言

眾所周知,Java中有多種針對文件的操作類,以面向字節流和字符流可分為兩大類,這里以寫入為例:

面向字節流的:FileOutputStream 和 BufferedOutputStream

面向字符流的:FileWriter 和 BufferedWriter

近年來發展出New I/O ,也叫NIO,里面又包裝了兩個類:NewOutputStream 和 NewBufferedWriter

現在,我們建立測試程序,比較這些類寫入文件的性能。

機器配置

  •   Processor Name: Intel Core i7
  •   Processor Speed: 2.2 GHz
  •   Number of Processors: 1
  •   Total Number of Cores: 4
  •   L2 Cache (per Core): 256 KB
  •   L3 Cache: 6 MB
  •   Memory: 16 GB

測試程序

縱向比較:幾種文件操作類向文件中寫入相同行數的內容(每行內容均為“寫入文件Data\n”),比較其耗費時間

橫向比較:對於同一個文件操作類,比較寫入不同行數內容情況下所耗費時間;本文以2的次方指數級增長行數

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.*;
  4 import java.nio.file.Files;
  5 import java.nio.file.Paths;
  6 
  7 public class testFileIO {
  8 
  9     public static void testDriver () throws IOException {
 10         int maxlineNum = 100000001;//寫入文件的最大行數
 11         int startlineNum = 1;//寫入文件的行數
 12         int Multiplying = 2;//行數增長倍率
 13 
 14         long begin = 0L;
 15         long end = 0L;
 16 
 17         //將時間統計寫入文件Result.txt中
 18         FileWriter fileWriter = new FileWriter("./Result.txt", true);
 19         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
 20 
 21         System.out.println("Test FileOutputStream begin.");
 22         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 23             begin = System.currentTimeMillis();
 24             testFileOutputStream(lineNum);
 25             end = System.currentTimeMillis();
 26             long timeElapse_FileOutputStream = end - begin;
 27             bufferedWriter.write(String.valueOf(timeElapse_FileOutputStream)+"\t");
 28         }
 29         System.out.println("Test FileOutputStream end.\n");
 30 
 31         System.out.println("Test BufferedOutputStream begin.");
 32         bufferedWriter.write("\n");
 33         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 34             begin = System.currentTimeMillis();
 35             testBufferedOutputStream(lineNum);
 36             end = System.currentTimeMillis();
 37             long timeElapse_BufferedOutputStream = end - begin;
 38             bufferedWriter.write(String.valueOf(timeElapse_BufferedOutputStream)+"\t");
 39         }
 40         System.out.println("Test BufferedOutputStream end.\n");
 41 
 42         System.out.println("Test FileWriter begin.");
 43         bufferedWriter.write("\n");
 44         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 45             begin = System.currentTimeMillis();
 46             testFileWriter(lineNum);
 47             end = System.currentTimeMillis();
 48             long timeElapse_FileWriter = end - begin;
 49             bufferedWriter.write(String.valueOf(timeElapse_FileWriter)+"\t");
 50         }
 51         System.out.println("Test FileWriter end.\n");
 52 
 53         System.out.println("Test BufferedWriter begin.");
 54         bufferedWriter.write("\n");
 55         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 56             begin = System.currentTimeMillis();
 57             testBufferedWriter(lineNum);
 58             end = System.currentTimeMillis();
 59             long timeElapse_BufferedWriter = end - begin;
 60             bufferedWriter.write(String.valueOf(timeElapse_BufferedWriter)+"\t");
 61         }
 62         System.out.println("Test BufferedWriter end.\n");
 63 
 64         System.out.println("Test NewOutputStream begin.");
 65         bufferedWriter.write("\n");
 66         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 67             begin = System.currentTimeMillis();
 68             testNewOutputStream(lineNum);
 69             end = System.currentTimeMillis();
 70             long timeElapse_NewOutputStream = end - begin;
 71             bufferedWriter.write(String.valueOf(timeElapse_NewOutputStream)+"\t");
 72         }
 73         System.out.println("Test NewOutputStream end.\n");
 74 
 75         System.out.println("Test NewBufferedWriter begin.");
 76         bufferedWriter.write("\n");
 77         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 78             begin = System.currentTimeMillis();
 79             testNewBufferedWriter(lineNum);
 80             end = System.currentTimeMillis();
 81             long timeElapse_NewBufferedWriter = end - begin;
 82             bufferedWriter.write(String.valueOf(timeElapse_NewBufferedWriter)+"\t");
 83         }
 84         System.out.println("Test NewOutputStream end.\n");
 85 
 86         bufferedWriter.close();
 87     }
 88 
 89     /************************** I/O *****************************/
 90     //面向字節
 91     public static void testFileOutputStream (int lineNum) throws IOException {
 92         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testFileOutputStream.txt"));
 93         while (--lineNum > 0) {
 94             fileOutputStream.write("寫入文件Data\n".getBytes());
 95         }
 96         fileOutputStream.close();
 97     }
 98 
 99     public static void testBufferedOutputStream (int lineNum) throws IOException {
100         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testBufferedOutputStream.txt"));
101         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
102         while (--lineNum > 0) {
103             bufferedOutputStream.write("寫入文件Data\n".getBytes());
104         }
105         bufferedOutputStream.close();
106     }
107 
108     //面向字符
109     public static void testFileWriter (int lineNum) throws IOException {
110         FileWriter fileWriter = new FileWriter("./testFileWriter.txt");
111         while (--lineNum > 0) {
112             fileWriter.write("寫入文件Data\n");
113         }
114         fileWriter.close();
115     }
116 
117     public static void testBufferedWriter (int lineNum) throws IOException {
118         FileWriter fileWriter = new FileWriter("./testBufferedWriter.txt");
119         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
120         while (--lineNum > 0) {
121             bufferedWriter.write("寫入文件Data\n");
122         }
123         bufferedWriter.close();
124     }
125 
126 
127     /************************** NIO ****************************/
128     public static void testNewOutputStream (int lineNum) throws IOException {
129         OutputStream outputStream = Files.newOutputStream(Paths.get("./testNewOutputStream.txt"));
130         while (--lineNum > 0) {
131             outputStream.write("寫入文件Data\n".getBytes());
132         }
133         outputStream.close();
134     }
135 
136     public static void testNewBufferedWriter (int lineNum) throws IOException {
137         BufferedWriter newBufferedReader = Files.newBufferedWriter(Paths.get("./testNewBufferedWriter.txt"));
138         while (--lineNum > 0) {
139             newBufferedReader.write("寫入文件Data\n");
140         }
141         newBufferedReader.close();
142     }
143 
144 
145     public static void main (String[] args) throws IOException {
146         //多次測試時可清空result.txt文件
147         FileWriter fileWriter = new FileWriter("./Result.txt");
148         testDriver();
149     }
150 }

測試結果

從上圖可以看出,寫入行數超過20W以上時,FileOutputStream和NewOutputStream耗費時間遠遠超出其他4個類。為了清晰,讓我們放大其他4個類的圖:

 

可以看出,這4個類中,BufferWriter和NewBufferedWriter所耗費時間更少,但總體差別不是很大。

讓我們再來看看,寫入26W行數據以下時的情況:

     

 可以看出,在數據量較小的情況下,這4個類所耗費時間的差異並不是很大,在更小的數據量下,它們的效率幾乎沒有差別。

后記

從以上分析可知(注意橫坐標寫入行數是指數級增加的),各個類的時間復雜度大致為O(k),其中不同的類的k不同,導致了最終巨大的差異。

這里只給出了測試結果,並未很深入地分析其底層實現原理,歡迎評論區留言。

另外,我沒有在其他機器測試,有興趣的小伙伴可以將自己的測試結果發出來,共同進步^_^

附件

本次測試數據結果(若看不清,可以將瀏覽器字體放大,或下載到本地看)

 

~~~~~~~~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~~~~~

評論區小伙伴“ andorxor”提出:

XXXOutputStream是用來寫二進制的,你把字符串轉換成字節數組再寫自然就慢了,主要慢在轉換的過程。

因此,將程序修改,提前把字符和字節內容都准備好,再次驗證。新程序如下:

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.*;
  4 import java.nio.file.Files;
  5 import java.nio.file.Paths;
  6 
  7 public class testFileIO {
  8 
  9 
 10     public static void testDriver () throws IOException {
 11         int maxlineNum = 100000001;//寫入文件的最大行數
 12         int startlineNum = 1;//寫入文件的行數
 13         int Multiplying = 2;//行數增長倍率
 14 
 15         String contentChars = "寫入文件Data\n";//每行的內容(字符流)
 16         byte[] contentBytes = "寫入文件Data\n".getBytes();//每行的內容(字節流)
 17 
 18         long begin = 0L;
 19         long end = 0L;
 20 
 21         //將時間統計寫入文件Result.txt中
 22         FileWriter fileWriter = new FileWriter("./Result.txt", true);
 23         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
 24 
 25         System.out.println("Test FileOutputStream begin.");
 26         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 27             begin = System.currentTimeMillis();
 28             testFileOutputStream(lineNum,contentBytes);
 29             end = System.currentTimeMillis();
 30             long timeElapse_FileOutputStream = end - begin;
 31             bufferedWriter.write(String.valueOf(timeElapse_FileOutputStream)+"\t");
 32         }
 33         System.out.println("Test FileOutputStream end.\n");
 34 
 35         System.out.println("Test BufferedOutputStream begin.");
 36         bufferedWriter.write("\n");
 37         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 38             begin = System.currentTimeMillis();
 39             testBufferedOutputStream(lineNum,contentBytes);
 40             end = System.currentTimeMillis();
 41             long timeElapse_BufferedOutputStream = end - begin;
 42             bufferedWriter.write(String.valueOf(timeElapse_BufferedOutputStream)+"\t");
 43         }
 44         System.out.println("Test BufferedOutputStream end.\n");
 45 
 46         System.out.println("Test FileWriter begin.");
 47         bufferedWriter.write("\n");
 48         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 49             begin = System.currentTimeMillis();
 50             testFileWriter(lineNum,contentChars);
 51             end = System.currentTimeMillis();
 52             long timeElapse_FileWriter = end - begin;
 53             bufferedWriter.write(String.valueOf(timeElapse_FileWriter)+"\t");
 54         }
 55         System.out.println("Test FileWriter end.\n");
 56 
 57         System.out.println("Test BufferedWriter begin.");
 58         bufferedWriter.write("\n");
 59         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 60             begin = System.currentTimeMillis();
 61             testBufferedWriter(lineNum,contentChars);
 62             end = System.currentTimeMillis();
 63             long timeElapse_BufferedWriter = end - begin;
 64             bufferedWriter.write(String.valueOf(timeElapse_BufferedWriter)+"\t");
 65         }
 66         System.out.println("Test BufferedWriter end.\n");
 67 
 68         System.out.println("Test NewOutputStream begin.");
 69         bufferedWriter.write("\n");
 70         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 71             begin = System.currentTimeMillis();
 72             testNewOutputStream(lineNum,contentBytes);
 73             end = System.currentTimeMillis();
 74             long timeElapse_NewOutputStream = end - begin;
 75             bufferedWriter.write(String.valueOf(timeElapse_NewOutputStream)+"\t");
 76         }
 77         System.out.println("Test NewOutputStream end.\n");
 78 
 79         System.out.println("Test NewBufferedWriter begin.");
 80         bufferedWriter.write("\n");
 81         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 82             begin = System.currentTimeMillis();
 83             testNewBufferedWriter(lineNum,contentChars);
 84             end = System.currentTimeMillis();
 85             long timeElapse_NewBufferedWriter = end - begin;
 86             bufferedWriter.write(String.valueOf(timeElapse_NewBufferedWriter)+"\t");
 87         }
 88         System.out.println("Test NewOutputStream end.\n");
 89 
 90         bufferedWriter.close();
 91     }
 92 
 93     /************************** I/O *****************************/
 94     //面向字節
 95     public static void testFileOutputStream (int lineNum, byte[] content) throws IOException {
 96         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testFileOutputStream.txt"));
 97         while (--lineNum > 0) {
 98             fileOutputStream.write(content);
 99         }
100         fileOutputStream.close();
101     }
102 
103     public static void testBufferedOutputStream (int lineNum, byte[] content) throws IOException {
104         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testBufferedOutputStream.txt"));
105         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
106         while (--lineNum > 0) {
107             bufferedOutputStream.write(content);
108         }
109         bufferedOutputStream.close();
110     }
111 
112     //面向字符
113     public static void testFileWriter (int lineNum, String content) throws IOException {
114         FileWriter fileWriter = new FileWriter("./testFileWriter.txt");
115         while (--lineNum > 0) {
116             fileWriter.write(content);
117         }
118         fileWriter.close();
119     }
120 
121     public static void testBufferedWriter (int lineNum, String content) throws IOException {
122         FileWriter fileWriter = new FileWriter("./testBufferedWriter.txt");
123         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
124         while (--lineNum > 0) {
125             bufferedWriter.write(content);
126         }
127         bufferedWriter.close();
128     }
129 
130 
131     /************************** NIO ****************************/
132     public static void testNewOutputStream (int lineNum, byte[] content) throws IOException {
133         OutputStream outputStream = Files.newOutputStream(Paths.get("./testNewOutputStream.txt"));
134         while (--lineNum > 0) {
135             outputStream.write(content);
136         }
137         outputStream.close();
138     }
139 
140     public static void testNewBufferedWriter (int lineNum,String content) throws IOException {
141         BufferedWriter newBufferedReader = Files.newBufferedWriter(Paths.get("./testNewBufferedWriter.txt"));
142         while (--lineNum > 0) {
143             newBufferedReader.write(content);
144         }
145         newBufferedReader.close();
146     }
147 
148 
149     public static void main (String[] args) throws IOException {
150         //多次測試時可清空result.txt文件
151         FileWriter fileWriter = new FileWriter("./Result.txt");
152         testDriver();
153     }
154 }
View Code

結果為:

可以看出和前面的案例幾乎沒有差異(圖就不畫了)。

所以XXXOutputStream效率低的原因並不是字符串轉換成字節數組,而是其本身的實現方式所致。

 

~~~~~~~~~~~~~~~~~~~~~分割線:底層實現原理淺談~~~~~~~~~~~~~~~~~~~~~~~

其實,計算機中都是針對字節操作的(即字符都要經過編碼轉換為字節),那么問題來了,FileOutputStream為什么比FileWriter(FileWriter內部還有FileOutputStream轉換操作,具體看源碼)還要慢呢?且慢,讓我們把寫入文件的數據改一下:

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.*;
  4 import java.nio.file.Files;
  5 import java.nio.file.Paths;
  6 
  7 public class testFileIO {
  8 
  9 
 10     public static void testDriver () throws IOException {
 11         int maxlineNum = 500001;//寫入文件的最大行數
 12         int startlineNum = 1;//寫入文件的行數
 13         int Multiplying = 2;//行數增長倍率
 14 
 15         String baseContent = "背景\n" +
 16             "考慮以下場景:\n" +
 17             "\n" +
 18             "InfoTable(信息表):\n" +
 19             "\n" +
 20             "Name\tGender\tAge\tScore\n" +
 21             "張三\t男\t21\t90\n" +
 22             "李四\t女\t20\t87\n" +
 23             "王五\t男\t22\t92\n" +
 24             "趙六\t女\t19\t94\n" +
 25             "孫七\t女\t23\t88\n" +
 26             "周八\t男\t20\t91\n" +
 27             "StatusTable(狀態表,指是否有在考試之前復習):\n" +
 28             "\n" +
 29             "Name\thasReview\n" +
 30             "張三\t是\n" +
 31             "李四\t否\n" +
 32             "王五\t是\n" +
 33             "趙六\t是\n" +
 34             "孫七\t否\n" +
 35             "周八\t是\n" +
 36             "現在,我想知道所有復習過的學生的成績,可以利用mysql中的子查詢來實現:\n" +
 37             "\n" +
 38             "SELECT Score \n" +
 39             "FROM InfoTable \n" +
 40             "WHERE Name in (SELECT Name \n" +
 41             "               FROM StatusTable \n" +
 42             "               WHERE hasReview = '是');\n" +
 43             "這種方式非常方便,我們只要把查詢條件寫出來,剩下的操作都由mysql來處理。而在實際場景中,為了減少底層耦合,我們一般不通過mysql中的子查詢方式聯表查詢,而是先執行子查詢得到結果集,再以結果集作為條件執行外層查詢。通常情況下,子查詢和外層查詢由上層的不同服務執行,這樣就在一定程度上達到了底層數據庫解耦的目的。注意這種實現方式將mysql內部的一部分復雜操作拋給了我們。這時,Mybatis中的foreach標簽就有了用武之地。\n" +
 44             "\n" +
 45             "Mybatis 中foreach標簽的用法\n" +
 46             "還以剛才的例子來說,先執行子查詢\n" +
 47             "\n" +
 48             "SELECT Name FROM StatusTable WHERE hasReview = '是'\n" +
 49             "再執行外層查詢,就是\n" +
 50             "\n" +
 51             "SELECT Score \n" +
 52             "FROM InfoTable \n" +
 53             "WHERE Name in ('張三' , '王五', '趙六', '周八');\n" +
 54             "也就是一個批量查詢操作,將其抽象一下(假設有三個條件):\n" +
 55             "\n" +
 56             "SELECT * \n" +
 57             "FROM <tableName> \n" +
 58             "WHERE <ColumnName> IN (<case1>,<case2>,<case3>)\n" +
 59             "實際情況中,case可能遠不止3個,這時可以在XXXMapper.xml文件中利用Mybatis中的foreach編寫sql語句:\n" +
 60             "\n" +
 61             "SELECT * \n" +
 62             "FROM <tableName> \n" +
 63             "WHERE <ColumnName> IN \n" +
 64             "<foreach collection=\"list\" index=\"index\" item=\"item\" open=\"(\" separator=\",\" close=\")\">\n" +
 65             "    #{item}\n" +
 66             "</foreach>\n" +
 67             "就可以實現相同的效果了。\n" +
 68             "\n" +
 69             "那么問題來了,foreach標簽中各種參數是什么含義呢?\n" +
 70             "\n" +
 71             "collection\n" +
 72             "如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list\n" +
 73             "如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array\n" +
 74             "如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在breast里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map里面的key\n" +
 75             "index 集合迭代位置\n" +
 76             "item 集合中的每一個元素別名\n" +
 77             "open 開始符號,例如這里的(,就對應於IN (<case1>,<case2>,<case3>)中IN后面的第一個(\n" +
 78             "separator 分隔符,例如這里的,,就對應於IN (<case1>,<case2>,<case3>)中的,\n" +
 79             "close 結束符號,例如這里的),就對應於IN (<case1>,<case2>,<case3>)中<case3>后面的)\n" +
 80             "參考\n";
 81 
 82         String contentChars = baseContent;//每行的內容(字符流)
 83         byte[] contentBytes = baseContent.getBytes();//每行的內容(字節流)
 84 
 85         long begin = 0L;
 86         long end = 0L;
 87 
 88         //將時間統計寫入文件Result.txt中
 89         FileWriter fileWriter = new FileWriter("./Result.txt", true);
 90         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
 91 
 92         System.out.println("Test FileOutputStream begin.");
 93         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
 94             begin = System.currentTimeMillis();
 95             testFileOutputStream(lineNum,contentBytes);
 96             end = System.currentTimeMillis();
 97             long timeElapse_FileOutputStream = end - begin;
 98             bufferedWriter.write(String.valueOf(timeElapse_FileOutputStream)+"\t");
 99         }
100         System.out.println("Test FileOutputStream end.\n");
101 
102         System.out.println("Test BufferedOutputStream begin.");
103         bufferedWriter.write("\n");
104         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
105             begin = System.currentTimeMillis();
106             testBufferedOutputStream(lineNum,contentBytes);
107             end = System.currentTimeMillis();
108             long timeElapse_BufferedOutputStream = end - begin;
109             bufferedWriter.write(String.valueOf(timeElapse_BufferedOutputStream)+"\t");
110         }
111         System.out.println("Test BufferedOutputStream end.\n");
112 
113         System.out.println("Test FileWriter begin.");
114         bufferedWriter.write("\n");
115         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
116             begin = System.currentTimeMillis();
117             testFileWriter(lineNum,contentChars);
118             end = System.currentTimeMillis();
119             long timeElapse_FileWriter = end - begin;
120             bufferedWriter.write(String.valueOf(timeElapse_FileWriter)+"\t");
121         }
122         System.out.println("Test FileWriter end.\n");
123 
124         System.out.println("Test BufferedWriter begin.");
125         bufferedWriter.write("\n");
126         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
127             begin = System.currentTimeMillis();
128             testBufferedWriter(lineNum,contentChars);
129             end = System.currentTimeMillis();
130             long timeElapse_BufferedWriter = end - begin;
131             bufferedWriter.write(String.valueOf(timeElapse_BufferedWriter)+"\t");
132         }
133         System.out.println("Test BufferedWriter end.\n");
134 
135         System.out.println("Test NewOutputStream begin.");
136         bufferedWriter.write("\n");
137         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
138             begin = System.currentTimeMillis();
139             testNewOutputStream(lineNum,contentBytes);
140             end = System.currentTimeMillis();
141             long timeElapse_NewOutputStream = end - begin;
142             bufferedWriter.write(String.valueOf(timeElapse_NewOutputStream)+"\t");
143         }
144         System.out.println("Test NewOutputStream end.\n");
145 
146         System.out.println("Test NewBufferedWriter begin.");
147         bufferedWriter.write("\n");
148         for (int lineNum = startlineNum; lineNum < maxlineNum; lineNum *= Multiplying) {
149             begin = System.currentTimeMillis();
150             testNewBufferedWriter(lineNum,contentChars);
151             end = System.currentTimeMillis();
152             long timeElapse_NewBufferedWriter = end - begin;
153             bufferedWriter.write(String.valueOf(timeElapse_NewBufferedWriter)+"\t");
154         }
155         System.out.println("Test NewOutputStream end.\n");
156 
157         bufferedWriter.close();
158     }
159 
160     /************************** I/O *****************************/
161     //面向字節
162     public static void testFileOutputStream (int lineNum, byte[] content) throws IOException {
163         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testFileOutputStream.txt"));
164         while (--lineNum > 0) {
165             fileOutputStream.write(content);
166         }
167         fileOutputStream.close();
168     }
169 
170     public static void testBufferedOutputStream (int lineNum, byte[] content) throws IOException {
171         FileOutputStream fileOutputStream = new FileOutputStream(new File("./testBufferedOutputStream.txt"));
172         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
173         while (--lineNum > 0) {
174             bufferedOutputStream.write(content);
175         }
176         bufferedOutputStream.close();
177     }
178 
179     //面向字符
180     public static void testFileWriter (int lineNum, String content) throws IOException {
181         FileWriter fileWriter = new FileWriter("./testFileWriter.txt");
182         while (--lineNum > 0) {
183             fileWriter.write(content);
184         }
185         fileWriter.close();
186     }
187 
188     public static void testBufferedWriter (int lineNum, String content) throws IOException {
189         FileWriter fileWriter = new FileWriter("./testBufferedWriter.txt");
190         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
191         while (--lineNum > 0) {
192             bufferedWriter.write(content);
193         }
194         bufferedWriter.close();
195     }
196 
197 
198     /************************** NIO ****************************/
199     public static void testNewOutputStream (int lineNum, byte[] content) throws IOException {
200         OutputStream outputStream = Files.newOutputStream(Paths.get("./testNewOutputStream.txt"));
201         while (--lineNum > 0) {
202             outputStream.write(content);
203         }
204         outputStream.close();
205     }
206 
207     public static void testNewBufferedWriter (int lineNum,String content) throws IOException {
208         BufferedWriter newBufferedReader = Files.newBufferedWriter(Paths.get("./testNewBufferedWriter.txt"));
209         while (--lineNum > 0) {
210             newBufferedReader.write(content);
211         }
212         newBufferedReader.close();
213     }
214 
215 
216     public static void main (String[] args) throws IOException {
217         //多次測試時可清空result.txt文件
218         FileWriter fileWriter = new FileWriter("./Result.txt");
219         testDriver();
220     }
221 }
View Code

這次數據量就很大了,結果也就變了:

所以,數據量很小的情況下,字符到字節的編碼操作帶來的性能降低幾乎忽略不計;而數據量很大的時候,編碼耗費的時間就很可觀了。至於為什么在小數據量的情況下FileWriter快很多,目前我認為是一次操作兩個字節所致(有了緩存之后就差不多了)。

 

參考

Java IO流學習總結


免責聲明!

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



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