何时在Java中使用哪个Writer子类; 常见做法

pos*_*def 20 java io subclass writer

我一直对Java中不同IO实现的数量略有混淆,现在我完全陷入了项目开发阶段,我花时间阅读有用的东西.

我已经意识到在的不同子之间没有新手友好的比较(除了API for Writer类的简短解释)Writer.所以我想我会解决这个问题,这些不同的子类有什么用呢?

例如,我通常使用一个FileWriter包裹着BufferedWriter我的输出到文件,但我总是被这样的事实所激怒,即没有println()类似的方法,并且必须使用newLine()每一行(使输出人类可读).PrintWriterprintln()方法,但没有支持追加的构造函数...

如果你能从你的经验中给我两分钱,或者你可能偶然发现一个好的指南/方法,我真的很感激.

编辑:感谢大家的回复,我非常感谢这里传递的信息.有点不幸的是,整个append()事情最终成为焦点,它仅仅意味着它作为一个例子.我的问题主要是指所有不同实现的需要和使用,我想在一些答案中有所提及.

选择一个答案很难被接受,因为有三个非常可靠的答案,每个答案都有助于我对问题的理解.我将不得不和Anon一起去,因为他的代表人数最少.积分(我认为他是SO的新手).他有15个答案,其中一些答案非常合理,并提出了0个问题.我会说,这是值得推广的好贡献.

话虽如此,ColinD和Jay也提供了非常好的答案,并指出了有趣的想法.特别是Jay关于Java自动包装的评论BufferedWriter值得注意.再次感谢你们,真的很感激!

Ano*_*non 9

这些java.io类通常遵循Decorator模式.因此,虽然PrintWriter没有您可能想要的特定构造函数,但它确实有一个构造函数需要另一个构造函数Writer,因此您可以执行以下操作:

FileOutputStream fos = null;
try
{
    fos = new FileOutputStream("foo.txt");
    PrintWriter out = new PrintWriter(
                          new BufferedWriter(
                              new OutputStreamWriter(fos, "UTF-8")));
    // do what you want to do
    out.flush();
    out.close();
}
finally
{
    // quietly close the FileOutputStream (see Jakarta Commons IOUtils)
}
Run Code Online (Sandbox Code Playgroud)

作为一般使用说明,您始终希望将低级Writer(例如FileWriterOutputStreamWriter)包装在a中BufferedWriter,以最大限度地减少实际的IO操作.但是,这意味着您需要显式刷新并关闭最外层的Writer,以确保写入所有内容.

然后你需要关闭一个finally块中的低级Writer ,以确保你不会泄漏资源.

编辑:

看看MForster的回答让我再看看FileWriter的API.我意识到它不需要一个明确的字符集,这是一个非常糟糕的事情.所以我编辑了我的代码片段,使用包含FileOutputStream一个OutputStreamWriter带有显式字符集的代码片段.


Col*_*inD 7

FileWriter通常不是一个可以接受的类.它不允许您指定Charset用于写入,这意味着您将遇到正在运行的平台的默认字符集.毋庸置疑,这使得无法一致地使用相同的字符集来读取和写入文本文件,并且可能导致数据损坏.

而不是使用FileWriter,你应该包装FileOutputStream一个OutputStreamWriter.OutputStreamWriter允许你指定一个字符集:

File file = ...
OutputStream fileOut = new FileOutputStream(file);
Writer writer = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
Run Code Online (Sandbox Code Playgroud)

要使用PrintWriter上面的内容,只需将其包装BufferedWriterPrintWriter:

PrintWriter printWriter = new PrintWriter(writer);
Run Code Online (Sandbox Code Playgroud)

可能也只使用PrintWriter,需要一个构造函数File和一个字符集的名称:

PrintWriter printWriter = new PrintWriter(file, "UTF-8");
Run Code Online (Sandbox Code Playgroud)

这适用于您的特定情况,并且实际上与上面的代码完全相同,但知道如何通过包装各个部分来构建它是很好的.

其他Writer类型主要用于特殊用途:

  • StringWriter只是一个Writer可以用来创建一个String.CharArrayWriter是一样的char[].
  • PipedWriter管道到PipedReader.

编辑:

我注意到你评论了另一个关于以这种方式创建作家的冗长的答案.请注意,像Guava这样的库可以帮助减少常见操作的冗长.例如,String将一个文件写入特定字符集中的文件.使用番石榴,你可以写:

Files.write(text, file, Charsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)

您还可以创建BufferedWriter如下:

BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8);
Run Code Online (Sandbox Code Playgroud)