jdk源码解析--PrintStream类

Posted 我的IT技术路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk源码解析--PrintStream类相关的知识,希望对你有一定的参考价值。

在输出流中,上节我们说了一下常用的文件输出流,本节我们看下过滤输出流的一种PrintStream。该流是最常用的输出流之一,主要实现各种数据的打印,也称为打印流。该流是一种装饰流,需要传入一个基本流作为底层。在介绍该流的使用之前,我们先通过一个简单的例子说明一下该流的使用方法。

1. public static void main(String[] args) throws IOException {  

2.         File file = new File("test.txt");  

3.         if (file.exists()){  

4.             try (FileOutputStream byteOut = new FileOutputStream(file);//先创建文件流  

5.                  PrintStream out = new PrintStream(byteOut)){//将文件流封装成打印流  

6.                 out.println(10);  

7.                 out.println("it is a test");//文件中显示两行,一行是10 ,一行 it is a test   

8.             }  

9.         }  

10.   

11.     }  

上面的例子还是比较简单的,用一个文件流作为底层,在上面封装一个打印流,可以打印各种不同的数据信息。现在我们看下PrintStream的类图:

 

上面的类图显示了打印流的整个继承关系,之前我们看完了输出流那部分的继承关系,现在我们看下打印流继承了Appendable接口,该接口的作用是在流中追加数据。该接口中定义了几个不同类型的追加方式的函数append

下面我们先看下这个流的结构:

1. public class PrintStream extends FilterOutputStream  

2.     implements Appendable, Closeable  

3. {  

4.   

5.     private final boolean autoFlush;//是否自动刷新标志  

6.     private boolean trouble = false;//  

7.     private Formatter formatter;//打印的格式  

8.     //以下两个的作用是保证在不断刷新流的同时刷新缓存区  

9.     private BufferedWriter textOut;  

10.     private OutputStreamWriter charOut;  

11.     //构造函数  

12.     private PrintStream(boolean autoFlush, OutputStream out) {  

13.         super(out);  

14.         this.autoFlush = autoFlush;  

15.         this.charOut = new OutputStreamWriter(this);  

16.         this.textOut = new BufferedWriter(charOut);  

17.     }  

18.   

19.     private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {  

20.         super(out);  

21.         this.autoFlush = autoFlush;  

22.         this.charOut = new OutputStreamWriter(this, charset);  

23.         this.textOut = new BufferedWriter(charOut);  

24.     }  

25.   

26.      private PrintStream(boolean autoFlush, Charset charset, OutputStream out)  

27.         throws UnsupportedEncodingException  

28.     {  

29.         this(autoFlush, out, charset);  

30.     }  

31.     public PrintStream(OutputStream out) {  

32.         this(out, false);  

33.     }  

34.     public PrintStream(OutputStream out, boolean autoFlush) {  

35.         this(autoFlush, requireNonNull(out, "Null output stream"));  

36.     }  

37.     public PrintStream(OutputStream out, boolean autoFlush, String encoding)  

38.         throws UnsupportedEncodingException  

39.     {  

40.         this(autoFlush,requireNonNull(out, "Null output stream"),toCharset(encoding));  

41.     }  

42.     public PrintStream(String fileName) throws FileNotFoundException {  

43.         this(falsenew FileOutputStream(fileName));  

44.     }  

45.     public PrintStream(String fileName, String csn)  

46.         throws FileNotFoundException, UnsupportedEncodingException  

47.     {  

48.         // ensure charset is checked before the file is opened  

49.         this(false, toCharset(csn), new FileOutputStream(fileName));  

50.     }  

51.     public PrintStream(File file) throws FileNotFoundException {  

52.         this(falsenew FileOutputStream(file));  

53.     }  

54.     public PrintStream(File file, String csn)  

55.         throws FileNotFoundException, UnsupportedEncodingException  

56.     {  

57.         // ensure charset is checked before the file is opened  

58.         this(false, toCharset(csn), new FileOutputStream(file));  

59.     }  

现在看下其他的功能函数:

Flush:刷新

1. public void flush() {  

2.         synchronized (this) {//加锁  

3.             try {  

4.                 ensureOpen();//确保流是打开的  

5.                 out.flush();//调用底层的刷新  

6.             }  

7.             catch (IOException x) {  

8.                 trouble = true;  

9.             }  

10.         }  

11.     }  

12. private void ensureOpen() throws IOException {  

13.         if (out == null)//判断out是否为null  

14.             throw new IOException("Stream closed");  

15.     }  

Write:写入数据

1. public void write(int b) {//写入一个ascall码值  

2.         try {  

3.             synchronized (this) {//加锁  

4.                 ensureOpen();//确保流是打开的  

5.                 out.write(b);//写入数据  

6.                 if ((b == '\n') && autoFlush)  

7.                     out.flush();  

8.             }  

9.         }  

10.         catch (InterruptedIOException x) {  

11.             Thread.currentThread().interrupt();  

12.         }  

13.         catch (IOException x) {//设置异常标志  

14.             trouble = true;  

15.         }  

16.     }  

17. //和上面类似,写入一个字节数组,off为开始点,len为长度  

18. public void write(byte buf[], int off, int len) {  

19.         try {  

20.             synchronized (this) {  

21.                 ensureOpen();  

22.                 out.write(buf, off, len);  

23.                 if (autoFlush)  

24.                     out.flush();  

25.             }  

26.         }  

27.         catch (InterruptedIOException x) {  

28.             Thread.currentThread().interrupt();  

29.         }  

30.         catch (IOException x) {  

31.             trouble = true;  

32.         }  

33.     }  

Print:打印,和write类似,但是可以输入java基本类型的数据

1. public void print(Object obj) {  

2.         write(String.valueOf(obj));  

3.     }  

4. //通过textOut和charOut两个buffer缓存区保证不断刷新流的缓冲buf  

5. private void write(String s) {  

6.         try {  

7.             synchronized (this) {//加锁  

8.                 ensureOpen();  

9.                 textOut.write(s);//写入数据到textOut  

10.                 textOut.flushBuffer();//开始刷新  

11.                 charOut.flushBuffer();  

12.                 if (autoFlush && (s.indexOf('\n') >= 0))  

13.                     out.flush();//输出刷新  

14.             }  

15.         }  

16.         catch (InterruptedIOException x) {  

17.             Thread.currentThread().interrupt();  

18.         }  

19.         catch (IOException x) {  

20.             trouble = true;  

21.         }  

22.     }  

其他的打印都是类似的。主要是调用底层的write的写入str字符串。

Println:这个每次打印一次就加一个换行

1. public void println(String x) {  

2.         synchronized (this) {  

3.             print(x);  

4.             newLine();  

5.         }  

6.     }  

7. private void newLine() {  

8.         try {  

9.             synchronized (this) {  

10.                 ensureOpen();  

11.                 textOut.newLine();//输入换行符  

12.                 textOut.flushBuffer();  

13.                 charOut.flushBuffer();  

14.                 if (autoFlush)  

15.                     out.flush();  

16.             }  

17.         }  

18.         catch (InterruptedIOException x) {  

19.             Thread.currentThread().interrupt();  

20.         }  

21.         catch (IOException x) {  

22.             trouble = true;  

23.         }  

24.     }  

25. public void newLine() throws IOException {  

26.         write(lineSeparator);//增加输入一个换行符  

27.     }  

Append:追加

1. public PrintStream append(CharSequence csq) {  

2.         if (csq == null)  

3.             print("null");  

4.         else  

5.             print(csq.toString());//继续增加的输入到流中,因为print使用了两个buf存入相应的数据  

6.         return this;  

7.     }  

还有一个format函数,实现字符串的标准化,相对简单,那么打印流的代码就到这里。

 


以上是关于jdk源码解析--PrintStream类的主要内容,如果未能解决你的问题,请参考以下文章

jdk源码解析--AbstractStringBuilder类

jdk源码解析--String 类

jdk源码解析--BitSet类

jdk源码解析--Writer类

jdk源码解析--Condition类

jdk源码解析--ThreadPoolExecutor类