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

2022-09-02 10:22:53

我一直对Java中不同IO实现的数量感到有些困惑,现在我完全陷入了我的项目开发,我正在花时间阅读有用的东西。

我意识到,在类的不同子类之间没有新手友好的比较(除了API for Writer类的简短解释)。所以我想我会抛开一个问题,那些不同的子类有什么好处?Writer

例如,我通常使用a包装来输出文件,但我一直对没有类似方法的事实感到恼火,并且必须使用每一行(以使输出人类可读)。有方法,但没有支持追加的构造函数,但是...FileWriterBufferedWriterprintln()newLine()PrintWriterprintln()

如果您能从您的经验中给我两美分,或者您可能偶然发现的一个很好的指南/操作方法,我将不胜感激。

编辑:感谢大家的回复,我真的很感激这里传递的信息。有点不幸的是,整个事情最终成为焦点,它只是一个例子。我的问题主要是指所有不同实现的需求和使用,我想在几个答案中都提到了这一点。append()

很难选择一个答案被接受,因为有三个非常可靠的答案,每个答案都有助于我对这个问题的理解。我将不得不和Anon一起去,这次因为他得到的代表点最少(我推测他是SO的新手)。他有15个答案,其中一些非常好,问了0个问题。我想说,这是很好的贡献,这是值得推广的。

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


答案 1

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

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)
}

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

然后,您需要在块中关闭低级 Writer,以确保不会泄漏资源。finally

编辑

看着MForster的答案,让我又看了一眼FileWriter的API。我意识到它不需要明确的字符集,这是一件非常糟糕的事情。因此,我编辑了我的代码片段,以使用采用显式字符集的包装。FileOutputStreamOutputStreamWriter


答案 2

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

而不是使用 ,您应该将 a 包装在 . 允许您指定字符集:FileWriterFileOutputStreamOutputStreamWriterOutputStreamWriter

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

要与上述内容一起使用,只需将 包装在:PrintWriterBufferedWriterPrintWriter

PrintWriter printWriter = new PrintWriter(writer);

您也可以只使用采用 a 和字符集名称的构造函数:PrintWriterFile

PrintWriter printWriter = new PrintWriter(file, "UTF-8");

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

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

  • StringWriter只是一个可用于创建 . 对于 是相同的。WriterStringCharArrayWriterchar[]
  • PipedWriter用于管道连接到 .PipedReader

编辑:

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

Files.write(text, file, Charsets.UTF_8);

您也可以创建如下:BufferedWriter

BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8);

推荐