PrintStream与PrintWriter的区别

31

我已经搜索了网站并找到了一些答案,但是我很难理解这两个类之间的区别。有人能解释一下这两个类之间的区别吗?


3
PrintStream 处理字节(byte),而 PrintWriter 处理字符(char)。就是这样。 - Eng.Fouad
4
你可以使用PrintStream来写入字符串、字符、整数等数据类型。也许我对你所说的它处理字节的含义有所误解。 - i'mhungry
请查看以下链接:http://way2java.com/io/printstream-vs-printwriter/ - Jigar Pandya
可能是重复问题:https://dev59.com/SHE85IYBdhLWcg3wViE4 - siaooo
4
@Eng.Fouad:这是一个很好的问题,它值得更详细的回答,特别是如果你认为 System.out 实际上是一个 PrintStream 而不是 PrintWriter,而它的目的明显是打印字符而不是字节。请参见链接 https://dev59.com/SHE85IYBdhLWcg3wViE4,其中提供了额外的细节。 - mins
3个回答

27

PrintStream 是最初用于处理字符编码和其他数据类型的桥梁。如果您查看 java.io.OutputStream 的 javadoc,您将只看到写入两种不同数据类型(byteint)的方法。

在 JDK 的早期版本(1.0.x)中,当您想要写入字符时,可以采取以下两种方法之一:向输出流写入字节(假定字节采用系统默认字符集):

outputStream.write("foobar".getBytes());

或者将另一个outputStream包装在PrintStream中:

PrintStream printStream = new PrintStream(outputStream);
printStream.write("foobar");
看到区别了吗? PrintStream 负责将字符转换为字节,并进行编码(上面的构造函数使用系统默认编码,但您可以将其作为参数传递)。 它还提供了方便的方法来写入 doubleboolean 等等。

实际上,System.outSystem.err 都被定义为 PrintStream 实例。

然后 JDK 1.1 推出了,他们意识到需要更好地处理纯字符数据,因为 PrintStream 仍然具有基于字节的写入方法。所以他们推出了 Writer 抽象类,专门用于处理 charStringint 数据。

PrintWriter 添加了其他类型的方法,如 doubleboolean 等等。

现在,PrintWriter 还有 format() / printf() 等格式化打印方法等等。

一般而言,如果您正在编写字符数据,请使用 Writer 实例。如果您正在编写二进制(或混合)数据,请使用 OutputStream 实例。


1
历史真的很有帮助,它解释了为什么 System.outSystem.err 仍然是 PrintStream - Franklin Yu
1
如果PrintWriter真的是PrintStream的替代品,那为什么PrintStream没有被弃用呢? - DBear

10
根据PrintWriter的Javadoc

将对象的格式化表示输出到文本输出流。此类实现了PrintStream中的所有print方法。它不包含用于写入原始字节的方法,程序应使用未编码的字节流。

可以这样想:一个PrintStream位于某个OutputStream之上。由于输出流处理的是字节而不是字符,因此PrintStream必须负责将字符编码为字节。OutputStream“仅”将字节写入文件/控制台/套接字等。

另一方面,PrintWriter位于Writer之上。由于Writer负责将字符编码为字节,因此PrintWriter不会进行编码。它只知道换行符等。(是的,PrintWriters确实有用于接受File和OutputStream的构造函数,但那些只是便利。例如,PrintWriter(OutputStream))。

  

从现有的OutputStream创建一个没有自动换行的新PrintWriter。这个便利构造函数将创建必要的中间OutputStreamWriter,它将使用默认字符编码将字符转换为字节。

顺便说一句,如果您认为PrintWriter实际上没有多少用处,请记住,PrintWriter和PrintStream都会吸收来自打印逻辑的IOException


3
为了补充Matt的回答:
我比较了PrintStream和PrintWriter,这两个类最有用的部分是构造函数ClassName(String fileName, String charsetName)以及print()、println()、printf()/format()函数,这些函数都被这两个类支持。
它们之间的区别在于: 自从JDK1.0和JDK1.1版本以来,
构造函数:
PrintStream(OutputStream out, boolean autoFlush, String charsetName)
PrintWriter(Writer wr)
PrintWriter(Writer wr, boolean autoFlush)

FilterOutputStream/OutputStream继承的方法与Writer的区别在于它们处理的数据类型不同:bytechar

PrintStream.write(byte[] buffer, int offset, int count)
PrintStream.write(byte[] buffer)
PrintStream.write(int oneByte)

PrintWriter.write(int oneChar)
PrintWriter.write(char[] buf)
PrintWriter.write(char[] buf, int offset, int count)
PrintWriter.write(String str)
PrintWriter.write(String str, int offset, int count)

PrintStream.printf() 对应于 PrintWriter.format()

看起来在1.1版本中他们想出了一个更好的类,但不能删除旧的1.0类,因为这会破坏现有的程序。


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