Java里面BufferedWriter在超过设置的缓冲区大小时数据不会flush写入文件的问题

最近在写一个功能,用到了BufferedWriter这个类,因为一般在new这个类的时候很少说去显式指定缓冲区大小,默认都是8K的字符数组。然后我就想了些关于缓冲流里面缓冲区的细节问题,这个方法大家都知道,就是假如缓冲区没有满,需要手动执行flush或close来清空缓冲区并把数据写到文件中;如果缓冲区自己满了,就会自动写入到文件。于是我想测试一下第二句话的效果

如果缓冲区自己满了,就会自动写入到文件

然后我把代码写了个demo如下:

public static void Test1() throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("abc3\\noFlush.txt"), 2);
        bw.write(new char[]{'我','爱','你','祖','国'});
    }

显式指定缓冲区大小为2,按照目前的理解就是,write的数据大小是5,超出了缓冲区大小,那就在第一轮就会先在缓冲区存入“我、爱”这两个字符,缓冲区满了自动写入文件;第二轮存入“你、祖”,缓冲区满了又自动写入文件;最后一个“”字因为存在于缓冲区但还没有满,所以没有写入到文件。

但是!实际上noFlush.txt文件里面竟是空白一片!!

我就纳闷了,不是write的数据大小超过指定的缓冲区大小就会自动写入文件嘛?为啥我这个文件里面啥都没有。通俗来讲,解决办法就是在代码结尾使用flush或者close方法,这样就可以写入到文件了,但这并不是我要的效果。

我目的是想证明“如果缓冲区自己满了,就会自动写入到文件”。

后面查阅了很多关于缓冲区的细节资料,好像都并没有我想要的那个答案,绝大部分对于缓冲区的解释都偏向于满了会自动写入等等。

于是我咨询了一些大佬,大佬们给了我一个比较好的理解思路,说咱们在new BufferedWriter时指定的缓冲区大小只是给它自带的缓冲区设置的。其实还有一个缓冲区,就是在StreamEncoder这个类里面的缓冲区,这个类也自带一个缓冲区,并且大小默认固定为8K。两个缓冲区还是有区别的,毕竟是各自的缓冲区。

那么咱们的BufferedWriter和StreamEncoder又有什么关系呢?然后我搜到了一些相关的文章也找到了答案,文章地址在这,这篇文章提到了BufferedWriter在进行write时的一些过程。

按照我们目前的需求去理解write的细节:
我们现在write的数据长度不是5嘛?很明显超出了BufferedWriter内部缓冲区2的大小,
于是在BufferedWriter.write(cbuf, off, len) 里,有一段比较重要的方法逻辑:

如果数据长度超过缓冲区的大小,就会执行如下代码:

flushBuffer();
//这个flushBuffer方法里面会先判断:如果nextChar为0就return
//nextChar是字符缓冲区中的已存储元素的位置,初始化默认为0
//程序走到该方法时,nextChar也没改动过,所以这个方法返回return,相当于没有执行

//然后着重看下面这个方法
out.write(cbuf, off, len);

这个out对象就是你在new BufferedWriter时传入的Writer的子类实现,如传入的是FileWriter类

然后这个FileWriter类又是继承了OutputStreamWriter类,但因为这个FileWriter类没有自己的write方法,所以用的是父类OutputStreamWriterwrite(cbuf, off, len)方法,而OutputStreamWriterwrite方法又去执行StreamEncoderwrite方法,所以最后的落点是在StreamEncoder类这里。相关信息可以看下面图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

因此在前面代码demo里,即使我们设置了BufferedWriter内部缓冲区的大小为2,到这也用不上了,因为人家程序直接是走了out.write(cbuf,off,len)这个方法,完全没用到Buffer的缓冲区。

然后前面提到又因为StreamEncoder类里面自带8K的缓冲区,所以前面经过层层传递过来的“我爱你祖国”五个字符数据到了StreamEncoder类这儿,最终逻辑其实也就只是把这五个字符长度的数据放到8K的缓冲区里面

所以实际上对于StreamEncoder内部缓冲区来讲并没有塞满,这样一想,那既然没放满,我们也没有手动去flush和close,又怎能写入文件呢?

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值