Java:PrintStream和PrintWriter之间的区别


125

PrintStream和之间有什么区别PrintWriter?由于我经常将这两个类混在一起,因此它们有许多共同的方法。而且,我认为我们可以将它们用于完全相同的事物。但是必须有所不同,否则,只有一个阶级。

我搜索了档案,但找不到此问题。


1
+1好的问题,我也将这两个类混在一起,API文档也没有太大帮助。
helpermethod 2010年

另一个区别是自动冲洗的工作方式。对于写作者,输出中存在\ n字符会触发flush()。但是在字节流(PrintStream)中只有字节。然后,自动刷新将按照Javadoc中的描述进行工作,基于:“平台自己的行分隔符概念,而不是换行符”。
分钟

Answers:


129

听起来可能有些轻率,但PrintStream打印到OutputStream,然后PrintWriter打印到Writer。好的,我怀疑我会说出明显的观点是否有任何意义。但是还有更多。

那么,an OutputStream和a有Writer什么区别?两者都是流,主要区别是a OutputStream是字节流,而a Writer是字符流。

如果OutputStream处理字节,那又如何PrintStream.print(String)呢?它将使用默认平台编码将字符转换为字节。使用默认编码通常是一件坏事,因为从一个平台迁移到另一个平台时,它可能导致错误,尤其是在一个平台上生成文件并在另一个平台上使用该文件时。

使用Writer,您通常可以指定要使用的编码,避免任何平台依赖性。

为什么PrintStream在JDK中麻烦一个,因为主要目的是写字符而不是字节?PrintStream引入Reader / Writer字符流时,它早于JDK 1.1。我以为Sun PrintStream仅会因为它被如此广泛地使用而弃用了。(毕竟,你不希望每次调用System.out生成一个过时的API的警告!另外,从变更类型PrintStream,以PrintWriter在标准输出流将会破坏现有的应用程序。)


3
这也是我的想法-但事实并非如此。甚至PrintStream都在后台维护了Writer-如果将它传递给OutputStream,它将包装它。
乔恩·斯基特

3
@Jon-内部有一个Writer,但它写入OutputStream,因此最终效果是PrintStream写入OutputStream-进行字符到字节的转换,并使用默认平台编码。在PrintWriter中,对于char-> byte转换没有这种要求,您可以一直使用字符。
mdma,2010年

“默认字符集是在虚拟机启动期间确定的,通常取决于基础操作系统的语言环境和字符集。”,语言环境还会在某些平台上更改默认字符集。
达朱

7
从Java 1.5开始,PrintStream不限于使用平台默认编码。有些构造函数接受一个字符集名称。因此,PrintStream和之间的区别PrintWriter是a PrintWriter不能写原始字节,而这两个类包装了不同类型的目的地。
Ted Hopp

1
您可能还需要注意它们的行为上的显着差异,尽管它们有效地共享了接口PrintStreamprint()方法,但便捷函数调用write(),因此,如果启用,它们将触发自动刷新。PrintWriter另一方面,在呼叫至之后,将不会自动冲洗print()。我今天在向一些初学者展示Java,这吸引了一些不熟悉手动冲洗的学生。否则,您的答案就很好。
Robadob 2015年

61

使用,PrintStream您将无法使用平台的默认编码。

PrintStream stream = new PrintStream(output);

PrintWriter不过,您可以通过传递OutputStreamWriter带有特定编码的。

PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8"));

这样做的好处是,您可以控制编码字符的字符,以使字符最终不会成为mojibake


12
从1.4开始,有一个新的PrintStream构造函数采用编码PrintStream(OutputStream out, boolean autoFlush, String encoding)
artbristol 2011年

19

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


3

诸如PrintWriter之类的编写器用于文本输出,而流则用于二进制输出。作家为您处理字符集内容。流不是因为假设您不想要这种转换,否则将使您的二进制数据混乱,并且如果这样做的话,将使用写入器。


1
除PrintStream之外,因为该代码采用一种编码,所以它可以处理的内容比标准OutputStream还要多。
Simon Groenewolt,2010年

听起来很奇怪,System.out实际上是一个PrintStream,它的唯一目标是打印字符串。
2014年

“作家为您处理字符集” –只有作家负责将字符转换为字节。并非所有作家都这么做。
艾瓦尔(Aivar)2015年

2

您可以将原始字节写入流,而不能写入写入器。该PrintWriter的 javadoc中列出了其他方面的差异(最重要的是,能够设置一个流上的编码,因此它可以解释原始字节我会说)。


与PrintStream的一个可指定编码以及
Aivar

1

来自Horstmann的Java核心

Java资深人士可能会想知道PrintStream类和System.out发生了什么。在Java 1.0中,PrintStream类通过删除最高字节将所有Unicode字符截断为ASCII字符。(当时Unicode仍然是16位编码。)显然,这不是一种干净或可移植的方法,并且随着Java 1.1中读写器的引入而得以解决。为了与现有代码兼容,System.in,System.out和System.err仍是输入/输出流,而不是读取器和写入器。但是现在,PrintStream类在内部将Unicode字符转换为默认的主机编码,方法与PrintWriter相同。当您使用print和println方法时,类型为PrintStream的对象的行为与打印作者完全相同,


-3

Printwriter是对printstream的增强。

IE printstream用于特定目的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.