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(false, new 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(false, new 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类的主要内容,如果未能解决你的问题,请参考以下文章