BufferedWriter的write(String S)方法实际上是否缓冲?



根据Java SE 8文档,BufferedWriter类有以下自己的方法(w.r.t写入数据):

write(char[] cbuf, int off, int len)
write(int c)
write(String s, int off, int len)

正如我通过检查此类的源代码所确认的那样,它不会覆盖 Writer 的write(String s)方法。它只是继承了它。

我的问题是,给定以下代码:

public static void SaveTextToFile(String fileName, String data, boolean append) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File(fileName)));
bw.write(data);
bw.close();
}

在写入文件之前,数据是否会实际缓冲?如果不是,缓冲在哪些情况下发生?

write(String str)

Writer调用write(String str, int off, int len),在BufferedWriter覆盖。因此,您的数据将被缓冲。

推理BufferedWriter覆盖哪个方法是没有意义的。Writer类的所有非抽象方法都是根据其他方法实现的,最终最终得到其中一个抽象方法,因为Writer本身没有实现任何实际的写作逻辑(怎么可能呢?

由于Writer没有任何委托目标的概念,因此不可能在不被BufferedWriter子类拦截的情况下将任何方法委托给目标编写器,因为只有该子类知道目标。因此,所有write方法以及append方法都在BufferedWriter的控制之下,如果要写入的数据小于缓冲区的容量,则会进行缓冲。

也就是说,在您的示例中,

BufferedWriter bw = new BufferedWriter(new FileWriter(new File(fileName)));
bw.write(data);
bw.close();

缓冲没有优势,因为缓冲将在后续close()操作中直接刷新。因此,在最好的情况下,data大于缓冲区,您只是不必要地创建了一个BufferedWriter实例。但是,如果data小于缓冲区,则在实际写入数据之前,您还执行了从data到缓冲区的不必要的复制操作。

对于写入单个项目,缓冲没有任何意义。除此之外,提供一个实际上被忽略的append参数,假装不存在的功能是很危险的,特别是当这可能导致目标文件中的现有数据意外覆盖时。此外,应使用 try-with-resources 构造来安全地关闭编写器:

public static void SaveTextToFile(String fileName, String data, boolean append)
throws IOException {
try(Writer w = new FileWriter(fileName, append)) {
w.write(data);
}
}

// use StandardOpenOption.APPEND to append
public static void SaveTextToFile(String fileName, String data, OpenOption... o)
throws IOException {
Files.write(Paths.get(fileName),
Collections.singleton(data), Charset.defaultCharset(), o);
}

这可能会使您的方法过时,因为它仅委托给已经存在的方法

相关内容

最新更新