PrintStream类是大多数程序员都会遇到的第一个过滤器输出流,因为System.out就是一个PrintStream。不过,还可以使用下面两个构造函数将其他输出流串链到打印流:
public PrintStream(OutputStream out)public PrintStream(OutputStream out,boolean autoFlush)
默认情况下,打印流应当显式刷新输出。不过,如果autoFlush参数为true,那么每次写入1字节数组或换行,或者调用println()方法(这是PrintStream的方法,其实也就是System.out的方法)时,都会刷新输出流。
除了平常的write()、flush()和close()方法,PrintStream还有9个重载的print()方法和10个重载的println()方法:
public void print(boolean b)public void print(char c)public void print(int i)public void print(long l)public void print(float f)public void print(double d)public void print(char[] text)public void print(String s)public void print(Object o)public void println()public void println(boolean b)public void println(char c)public void println(int i)public void println(long l)public void println(float f)public void println(double d)public void println(char[] text)public void println(String s)public void println(Object o)
每个print()方法都将其参数以可预见的方式转换为一个字符串,再用默认的编码方式把字符串写入底层输出流。println()方法也完成相同的操作,但会在所写的行末尾追加一个与平台有关的行分隔符。在UNIX(包括 Mac OS X)下是换行符(\n),在Mac OS 9下是回车符(\r),在windows下是回车/换行对(\r\n)。
我们来看一个完整的例子:
package test;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.PrintStream;public class WriteInfo1 { public static void main(String[] args) { try { printInfo(); } catch (IOException e) { e.printStackTrace(); } } public static void printInfo() throws IOException { try(BufferedInputStream in = new BufferedInputStream(new FileInputStream("F:/in.txt")); PrintStream out = System.out){ int n = 0; /* * //注意这里的本地磁盘读文件,用available方法可以判断出文件大小,当然这不是绝对,99.99999%吧, * 呵呵,从网络中读就不行了 */ byte[] buf = new byte[in.available()]; while((n = in.read(buf)) != -1){ out.print(new String(buf)); } } }}
警告:PrintStream是有害的,网络程序员应当像躲避瘟疫一样避开它!!!!
第一个问题是println()的输出是与平台有关的。取决于运行代码的机器,各行有时用换行符分隔,有时则用回车符或者回车/换行对来分隔。写入控制台时这不会产生问题,但对于编写必须遵循明确协议的网络客户端和服务器而言,这却是灾难。大多数网络协议(如HTTP和Gnutela)明确指定行应当以回车/换行对结束。使用println()写出的程序很有可能可以在windows上正常工作,但在UNIX和Mac上无法工作。虽然许多服务器和客户端能够“宽容”地接受而且能处理不正确的行结束符,但偶尔也有例外。
第二个问题是PrintStream假定使用所在平台的默认编码方式。不过,这种编码方式可能不是服务器或客户端所期望的。例如,一个接收XML文件的Web浏览器希望文件以UTF-8或UTF16方式编码,除非服务器另行要求。不过,一个使用PrintStream的Web服务器可能会从一个美国本地化环境的windows系统发送CP1251编码的文件,或者从日本本地化环境的系统发送SJIS编码的文件,而不管客户端是否期望或理解这些编码方式。PrintStream不提供任何改变默认编码的机制。这个问题可以通过使用相关的PrintWriter类来修补。但是其他问题依旧。
第三个问题是PrintStream吞掉了所有异常。注意PrintStream中5个标准OutputStream方法的声明没有平常的throws IOException声明:
public abstract void write(int b)public void write(byte[] data)public void write(byte[] data,int offset,int length)public void void flush()public void close()
实际上,PrintStream要依靠一个过时的不充分的错误标志。如果底层流抛出一个异常,就会设置这个内部错误标志。要由程序员使用checkError()方法来检查这个标志的值:
public booleean checkError()
要对PrintStream完成任何错误检查,代码必须显式地检查每一个调用。此外,一旦出现在错误,就没有办法重置这个标志再进行进一步错误检测。也没有关于这个错误的更多信息。简而言之,PrintStream提供的错误通知对于不可靠的网络连接来说还远远不够。