为了账号安全,请及时绑定邮箱和手机立即绑定

Java文件操作类效率对比

标签:
Java

 


 

前言

众所周知,Java中有多种针对文件的操作类,以面向字节流和字符流可分为两大类,这里以写入为例:

面向字节流的:FileOutputStream 和 BufferedOutputStream

面向字符流的:FileWriter 和 BufferedWriter

近年来发展出New I/O ,也叫NIO,里面又包装了两个类:NewOutputStream 和 NewBufferedWriter

现在,我们建立测试程序,比较这些类写入文件的性能。

机器配置

" cdata_tag="style">

  •   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 }

复制代码

测试结果

https://img1.sycdn.imooc.com//5b8179b900018ef207400436.jpg

从上图可以看出,写入行数超过20W以上时,FileOutputStream和NewOutputStream耗费时间远远超出其他4个类。为了清晰,让我们放大其他4个类的图:

 

https://img1.sycdn.imooc.com//5b8179c10001d97207480418.jpg

可以看出,这4个类中,BufferWriter和NewBufferedWriter所耗费时间更少,但总体差别不是很大。

让我们再来看看,写入26W行数据以下时的情况:

     https://img1.sycdn.imooc.com//5b8179cd00015d3707030417.jpg

 可以看出,在数据量较小的情况下,这4个类所耗费时间的差异并不是很大,在更小的数据量下,它们的效率几乎没有差别。

后记

从以上分析可知(注意横坐标写入行数是指数级增加的),各个类的时间复杂度大致为O(k),其中不同的类的k不同,导致了最终巨大的差异。

这里只给出了测试结果,并未分析其底层实现原理,欢迎评论区留言。

另外,我没有在其他机器测试,有兴趣的小伙伴可以将自己的测试结果发出来,共同进步^_^

附件

本次测试数据结果(若看不清,可以将浏览器字体放大,或下载到本地看)

https://img1.sycdn.imooc.com//5b8179d90001763429070197.jpg

 

~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~

评论区小伙伴“ 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

结果为:

https://img1.sycdn.imooc.com//5b817abd0001da1c28780225.jpg

可以看出和前面的案例几乎没有差异(图就不画了)。

所以XXXOutputStream效率低的原因并不是字符串转换成字节数组,而是其本身的实现方式所致。

原文出处:https://www.cnblogs.com/xiaoxi666/p/9531893.html


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消