1. 程式人生 > >Java文件操作類效率對比

Java文件操作類效率對比

字符 name mem http .get space data args 內容

前言

眾所周知,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(1/kn),其中不同的類的k不同,導致了最終巨大的差異。

歡迎各位以底層實現分析更具體的時間復雜度,提出意見。

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

附件

本次測試數據結果(若看不清,可以下載到本地看)

技術分享圖片

Java文件操作類效率對比