博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FileWriter与BufferedWriter的适用场景
阅读量:6413 次
发布时间:2019-06-23

本文共 3931 字,大约阅读时间需要 13 分钟。

IO这块,各种Writer,Reader,让人眼晕

而在网上基本找不到在什么时候用哪个类,并且网上的IO demo 很多用法都是错的

在这简单的分析一下FileWriter与BufferedWriter

一、两个类的继承关系

FileWriter BufferedWriter

java.lang.Object

  ? java.io.Writer

    ? java.io.OutputStreamWriter

      ? java.io.FileWriter

java.lang.Object

  ? java.io.Writer

    ? java.io.BufferedWriter

 

 

 

 

 

 

由继承关系简单的来看,FileWriter是非常有意思的,它继承了OutputStreamWriter,这意味着它的写入是由FileOutputStream实现的,

这与我在前一篇中写到的内容相符合:字节用来与文件打交道,而字符用来和人打交道。

简单的说,FileWriter它的存在价值就在于方便人们写入字符串(即人能看懂的东西),它的内部依然是由FileOutputStream实现。

而BufferedWriter直接继承于java.io.Writer,看它的构造函数与用法,明显使用了

这意味着我们要使用它,就必须给他一个Writer才可以,在该文章中我们假设给定的Writer就是FileWriter。

 二、两个类的用法

 FileWriter  BufferedWriter
FileWriter fw = null;try {    fw = new FileWriter("c:/123456");    fw.write("0123456789");    fw.flush();} catch (IOException e) {    e.printStackTrace();} finally{    //关闭FileWriter    try {    if(null != fw)        fw.close();    } catch (IOException e) {        e.printStackTrace();    }}

 

FileWriter fw = null;BufferedWriter bw = null;try {    fw = new FileWriter("c:/123456");    //装饰模式,bw为包装对象,fw为真实对象    bw = new BufferedWriter(fw);    bw.write("0123456789");    bw.flush();} catch (IOException e) {    e.printStackTrace();} finally{    //关闭BufferedWriter    try {        if(null != bw)            bw.close();    } catch (IOException e) {        e.printStackTrace();    }    //关闭FileWriter    try {        if(null != fw)            fw.close();    } catch (IOException e) {        e.printStackTrace();    }}

 

从两个类的用法上来看,一个直接创建了FileWriter对象,写入数据

另一个,创建了FileWriter对象后,又创建了BufferedWriter对象,利用装饰模式操作BufferedWriter对象写入数据

同样的功能,两种方式都能实现,那么BufferedWriter存在的意义是什么?

三、BufferedWriter存在的意义

在网上能找到的答案基本都是: BufferedWriter输出时有缓冲区。

但是FileWriter也有啊,他们区别仅仅是FileWriter缓冲区大小为1024,而BufferedWriter默认缓冲区大小为8192,并且可以自己设置

为了测试,下面的程序分别用FileWriter、和BufferedWriter输出10M的字符串

FileWriter BufferedWriter
 
//接近10M的字符串StringBuilder sb = new StringBuilder();for(int i = 0; i < 10000000; i++){    sb.append("0123456789");}FileWriter fw = null;try {    fw = new FileWriter("c:/123456");    fw.write(sb.toString());    fw.flush();} catch (IOException e) {    e.printStackTrace();} finally{    //关闭FileWriter    try {        if(null != fw)            fw.close();    } catch (IOException e) {        e.printStackTrace();    }}

 

 
//接近10M的字符串StringBuilder sb = new StringBuilder();for(int i = 0; i < 10000000; i++){    sb.append("0123456789");}FileWriter fw = null;BufferedWriter bw = null;try {    fw = new FileWriter("c:/123456");    //装饰模式,bw为包装对象,fw为真实对象    bw = new BufferedWriter(fw);    bw.write(sb.toString());    bw.flush();} catch (IOException e) {    e.printStackTrace();} finally{    //关闭BufferedWriter    try {        if(null != bw)            bw.close();    } catch (IOException e) {        e.printStackTrace();    }    //关闭FileWriter    try {        if(null != fw)            fw.close();    } catch (IOException e) {        e.printStackTrace();    }}

 

714ms 600ms

从结果来看,他们的效率是有区别的,但区别并没到悬殊的地步

所以,这并不是他们区别的关键,在阅读两个类的源码后,我认为他们的最关键的区别在于:

FileWriter每次调用write()方法,就会调用一次OutputStreamWriter中的write()方法

而BufferedWriter只有在缓冲区满了才会调用OutputStreamWriter中的write()方法

为此我重写了FileWriter与OutputStreamWriter两个类,用来测试调用10000000次write()方法时OutputStreamWriter的write()方法执行次数

测试结果如下:

  FileWriter BufferedWriter
OutputStreamWrite的write()方法执行次数 10000000次 12207次
时间 1387ms 718ms

四、总结

BufferedWriter的执行速度确实要比FileWriter快,这方面的原因我还没找到。

但BufferedWriter在执行过程中增加了一层缓冲区,用来避免频繁执行OutputStreamWriter的write()方法

所以:

在一次性写入字符串到文件时可以直接调用FileWriter,在效率上影响不大

需多次写入字符串到文件时应调用BufferedWriter,可以避免频繁执行OutputStreamWriter的write()方法

五、题外话

网上能找到的区别大致上是

1、BufferedWriter输出时有缓冲区

2、BufferedWriter的write方法可以避免频繁的硬盘读写

这两种说法其实都是错误的

第一种:无论FileWriter还是BufferedWriter都有缓冲区,而缓冲区的大小1024已经足够

第二种:BufferedWriter的write方法无法实现避免频繁的硬盘读写,因为OutputStreamWriter的write()方法调用了StreamEncoder的write方法,而它的实现有缓冲区的存在,

    所以只有在缓冲区满的情况下才会写入硬盘,因此FileWriter还是BufferedWriter的硬盘读写应该一致。

    而真正的区别在于OutputStreamWriter的write()方法的调用次数

网上的东西很多是错的,包括这一篇,也不一定正确。

转载于:https://www.cnblogs.com/xjyh/p/4529809.html

你可能感兴趣的文章
学不好Python?我们分析看看正确的学习方法是什么-马哥教育
查看>>
面向对象复习日志二:Traits
查看>>
我的前端那些事--简介
查看>>
为什么在JavaScript中使用Prototype?[译]
查看>>
教妹学 Java:大有可为的集合
查看>>
微服务治理平台的RPC方案实现
查看>>
android 开发艺术view笔记
查看>>
程序员面试问答集锦,从容应对各种面试难题!
查看>>
你|可以为性感代言
查看>>
[仁润云技术团队]并发编程-(2)并发编程的目标
查看>>
Android 技术选型闲聊
查看>>
在 VS Code 中校验 Jenkinsfile
查看>>
数据结构与算法系列
查看>>
【直通BAT】剑指Offer 经典试题整理(4)
查看>>
Pyhton抓取BOSS直聘职位描述和数据清洗,很简单没有那么难
查看>>
Angular是什么框架?Angular如何入门?该看些什么资料,学习建议
查看>>
移动端网页调试
查看>>
JavaScript 引擎 V8 新机制:JIT-less 模式
查看>>
数据库之事务之间的隔离
查看>>
人工智能产业化面临多重挑战 应提前布局抢占先机
查看>>