流之过滤器流(PrintStream)

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提供的错误通知对于不可靠的网络连接来说还远远不够

你可能感兴趣的:(java-IO与网络编程)