PrintWriter写文件无输出但PrintStream写入正常,是什么原因?
两种写文件方式效果差异的根本原因
两种实现的结果不一样,核心是不同链路下的内存缓冲刷盘触发逻辑完全不同,和PrintWriter、PrintStream的类本身没有本质关联。
第一种写法为什么看不到写入结果
你用的第一种实现的完整数据流转链路是:PrintWriter -> BufferedWriter -> FileWriter -> 磁盘文件
问题就出在链路中间套的BufferedWriter上:
- 这个类的设计初衷是减少高频磁盘IO,默认会在JVM内存里开一块8KB大小的缓冲区,所有你通过
println写的内容,都会先暂存在这块内存里,不会立刻落到磁盘。 - 只有满足三个条件中的任意一个,缓冲区里的内容才会真正写到磁盘:
- 缓冲区攒够了8KB的内容,自动触发批量刷盘
- 手动调用
flush()方法强制把缓冲区内容刷出去 - 调用
close()方法关闭流(close执行时会先把所有缓冲区剩余内容刷到磁盘,再释放系统资源)
你只写了几个字节的"Hi",远达不到缓冲区的触发阈值,代码里既没手动flush、也没关流,内容就一直卡在JVM内存的缓冲区里,根本没走到磁盘层面,自然看不到文件里的写入效果。
第二种写法为什么能正常写入
第二种实现的完整数据流转链路是:PrintStream -> 内部字符缓冲区 -> 字节编码层 -> 磁盘文件
逻辑差异的核心点是:
- PrintStream在每次执行
println写入换行符时,不会等缓冲区攒够批量大小再统一输出,而是立刻把内部暂存的字符内容编码成字节,直接下发到底层的文件输出流。 - 你写入的"Hi"加换行符总共才3个字节,因为println触发了立刻下发的逻辑,内容在代码执行的瞬间就已经提交到操作系统的文件描述符里;就算没有显式调用close,当程序正常跑完退出时,操作系统也会自动把文件描述符里的缓存内容刷到磁盘,自然就能在文件里看到对应的文本。
补充提示
如果给第一种写法补上一句out.close()或者out.flush(),哪怕还是用PrintWriter套BufferedWriter的写法,也能正常把内容写到文件里,本质就是手动触发了缓冲区的刷盘动作。这也是Java开发写文件时的经典踩坑点:带内存缓冲的流如果忘记手动flush或close,在短文本写入的场景下,就很容易出现文件生成了但内容是空的情况。
内容的提问来源于stack exchange,提问作者esnoopy808
相关产品推荐
相关产品推荐

