Java:PrintStream和PrintWriter的区别

133

PrintStreamPrintWriter的区别是什么?由于它们有许多共同的方法,所以我经常混淆这两个类。此外,我认为我们可以将它们用于完全相同的事情。但必须有一个区别,否则就只会有一个类。

我已经搜索了档案,但找不到这个问题。


3
好问题,我也混淆这两个类,而且 API 文档也没有太大的帮助。 - helpermethod
2
另一个区别是autoflush的工作方式。对于写入器,输出中存在\n字符会触发flush()。但在字节流(PrintStream)中只有字节。然后,autoflush按照Javadoc中描述的基于“平台自己的行分隔符概念而不是换行符”进行工作。 - mins
6个回答

136
这听起来可能有些轻率,但是PrintStream将内容打印到OutputStream中,而PrintWriter则将内容打印到Writer中。虽然显而易见,但这里有更多的细节。 那么,OutputStreamWriter之间有什么区别呢?二者都是流,主要区别在于OutputStream是字节流,而Writer则是字符流。 如果OutputStream处理字节,那么PrintStream.print(String)又是怎么处理字符串的呢?它使用默认平台编码将字符转换为字节。使用默认编码通常是一个坏习惯,因为它可能会导致从一个平台到另一个平台时出现错误,特别是如果你在一个平台上生成文件并在另一个平台上使用时。 对于Writer,您通常需要指定要使用的编码,以避免任何平台依赖性问题。 既然主要意图是写字符而不是字节,为什么在JDK中还需要有PrintStream呢?PrintStream比JDK 1.1引入的Reader/Writer字符流更早。我想Sun会将其弃用,只是因为它被广泛使用。(毕竟,您不希望每次调用System.out都会生成弃用的API警告!此外,将标准输出流的类型从PrintStream更改为PrintWriter将破坏现有应用程序。)

3
我也曾经这么想过,但这不是真的。即使是PrintStream,在底层也会维护一个Writer——如果你传递给它一个OutputStream,它会对其进行包装。 - Jon Skeet
4
@Jon - 在内部有一个Writer,但它写入到OutputStream,因此净效果是PrintStream写入到OutputStream - 字符到字节的转换发生,并使用默认平台编码。在PrintWriter中没有char->byte转换的要求,您可以一直使用字符。 - mdma
9
自Java 1.5版本以来,PrintStream不再仅限于使用平台默认编码;它有接受字符集名称的构造函数。因此,PrintStreamPrintWriter之间的区别在于,PrintWriter不能写入原始字节,并且这两个类封装了不同类型的目标。 - Ted Hopp
2
你可能也值得注意它们行为上的一个重要区别,虽然它们有效地共享一个接口 PrintStreamprint() 方法是方便函数,会调用 write(),因此如果启用了自动刷新,它们会触发自动刷新。另一方面,PrintWriter 在调用 print() 后不会自动刷新。今天我正在演示一些初学者 Java,这让一些不熟悉手动刷新需求的学生感到困惑。除此之外,你的回答很棒。 - Robadob
1
@ieXcept 你说得对,也许我应该澄清一下我指的是默认行为,因为他们正在使用由某个库包装的 printwriter - Robadob
显示剩余4条评论

22
自从JDK 1.4以后,可以为PrintStream指定字符编码。因此,PrintStream和PrintWriter之间的区别仅在于自动刷新行为和PrintStream无法包装Writer。

4

像PrintWriter这样的写入器是用于文本输出的,而流是用于二进制输出的。这些写入器为您处理字符集问题。流不会处理,因为假定您不希望进行这种转换,否则会破坏二进制数据,并且如果需要的话,应该使用写入器。


1
除了PrintStream,因为它需要编码,所以它可以处理比标准OutputStream更多的内容。 - Simon Groenewolt
听起来很奇怪,System.out 的唯一目的是打印字符串,但它实际上是一个 PrintStream。 - mins
作者们为您处理字符集相关的事情 -- 只有那些处理将字符转换为字节的作者才会这样做。并非所有的作者都会这样做。 - Aivar

3

来自Horstmann的核心Java

Java老手可能会想知道PrintStream类和System.out去哪了。在Java 1.0中,PrintStream类只是通过丢弃最高字节将所有Unicode字符截断为ASCII字符。(当时,Unicode仍然是16位编码)。显然,这不是一种干净或可移植的方法,并且在Java 1.1引入读者和写者后进行了修复。为了兼容现有代码,System.in、System.out和System.err仍然是输入/输出流,而不是读者和写者。但现在,PrintStream类在内部以与PrintWriter相同的方式将Unicode字符转换为默认主机编码。当您使用print和println方法时,PrintStream类型的对象的行为与打印作者完全相同,但与打印作者不同,它们允许您使用write(int)和write(byte [])方法输出原始字节。


2
你可以将原始字节写入 Stream 而不是 Writer。PrintWriter javadoc 列出了其他差异(最重要的是,能够在流上设置编码,以便它可以解释原始字节)。

使用PrintStream,可以指定编码。 - Aivar

-3

PrintWriter 是 PrintStream 的增强版。

即为特定目的而设计的 PrintStream。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接