Java I/O 21 - PrintWriter

  关于 java.io.PrintWriter 的部分笔记,PrintWriter属于处理流的一种,提供了丰富的打印方法用来向目标位置打印输出字符内容。本文演示代码段的执行环境基于JDK版本1.7

概述

  PrintWriter用来向文本输出流打印经过格式化处理的数据。它实现了PrintStream中提及的所有打印方法,且这个类处理的都是字符数据,没有提供对字节数据的处理方法。和PrintStream不同的是,PrintWriter只会在调用了println, printf, 和format方法之后才会自动将数据推送到目标输出位置上(如果autoFlush = true)。而且,换行所用的行分隔符也是基于具体的运行机器的。

  PrintWriter还有一点特殊的地方就是,在调用其他方法都不会抛出I/O异常。如果要确认在调用PrintWriter处理输出数据的过程中是否产生了异常,可以通过调用checkError()进行确认。此这个过程中,如果流还没有关闭,会自动进行flush,同时返回错误状态标识位。

继承关系

1
2
3
4
// PrintWriter
--java.lang.Object
--java.io.Writer
--java.io.PrintWriter

实现接口

类名 实现接口
PrintWriter Closeable, AutoCloseable,Flushable, Appendable

PushbackReader

Constructor Summary

public PrintWriter(Writer out, boolean autoFlush)

1
2
3
4
5
6
7
public PrintWriter(Writer out, boolean autoFlush) {
super(out);
this.out = out;
this.autoFlush = autoFlush;
lineSeparator = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("line.separator"));
}

  初始化一个打印输出流。入参是一个字符输出流和一个是否自动flush的标识位,在完成相关字段的赋值后根据代码运行环境初始化一个适用于当前运行机器环境的行分隔符。

public PrintWriter(File file)

1
2
3
4
public PrintWriter(File file) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
false);
}

  初始一个打印输出流。将入参文件转成一个BufferWriter,之后调用构造器PrintWriter(Writer out, boolean autoFlush)完成初始化操作。

public PrintWriter(String fileName)

1
2
3
4
public PrintWriter(String fileName) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
false);
}

  初始一个打印输出流。将入参文件路径字符串转成一个含有文件字节输出流的BufferWriter,之后调用构造器PrintWriter(Writer out, boolean autoFlush)完成初始化操作。

public PrintWriter (Writer out)

1
2
3
public PrintWriter (Writer out) {
this(out, false);
}

  初始一个打印输出流。

public PrintWriter(OutputStream out, boolean autoFlush)

1
2
3
4
5
6
7
8
public PrintWriter(OutputStream out, boolean autoFlush) {
this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);

// save print stream for error propagation
if (out instanceof java.io.PrintStream) {
psOut = (PrintStream) out;
}
}

  依赖已有的字节输出流初始一个字符打印输出流。

public PrintWriter(OutputStream out)

1
2
3
public PrintWriter(OutputStream out) {
this(out, false);
}

  依赖已有的字节输出流初始一个字符打印输出流。通过调用构造器PrintWriter(OutputStream out, boolean autoFlush)完成初始化操作。

private PrintWriter(Charset charset, File file)

1
2
3
private PrintWriter(Charset charset, File file) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)), false);
}

  根据指定的编码字符集和文件对象初始化一个字符打印输出流。私有方法,不对外暴露。

public PrintWriter(String fileName, String csn)

1
2
3
4
public PrintWriter(String fileName, String csn)
throws FileNotFoundException, UnsupportedEncodingException {
this(toCharset(csn), new File(fileName));
}

  根据指定的编码字符集名称和文件路径字符串信息初始化一个字符打印输出流。通过调用构造器PrintWriter(Charset charset, File file)完成初始化操作。

public void PrintWriter(File file, String csn)

1
2
3
4
public void PrintWriter(File file, String csn)
throws FileNotFoundException, UnsupportedEncodingException {
this(toCharset(csn), file);
}

  根据指定的编码字符集名称和文件对象初始化一个字符打印输出流。通过调用构造器PrintWriter(Charset charset, File file)完成初始化操作。

部分方法

private static Charset toCharset(String csn)

1
2
3
4
5
6
7
8
9
private static Charset toCharset(String csn) throws UnsupportedEncodingException {
Objects.requireNonNull(csn, "charsetName");
try {
return Charset.forName(csn);
} catch (IllegalCharsetNameException | UnsupportedCharsetException unused) {
// UnsupportedEncodingException should be thrown
throw new UnsupportedEncodingException(csn);
}
}

  根据字符集名称取得对应的字符集Charset对象。

private void ensureOpen()

1
2
3
4
private void ensureOpen() throws IOException {
if (out == null)
throw new IOException("Stream closed");
}

  检查当前底层输出流是否开启且可用。

public boolean checkError()

1
2
3
4
5
6
7
8
9
10
11
12
public boolean checkError() {
if (out != null) {
flush();
}
if (out instanceof java.io.PrintWriter) {
PrintWriter pw = (PrintWriter) out;
return pw.checkError();
} else if (psOut != null) {
return psOut.checkError();
}
return trouble;
}

  在当前输出流尚未关闭的情况下将当前输出流中的内容推送到目标输出位置,同时返回异常状态标志位。

protected void setError()

1
2
3
protected void setError() {
trouble = true;
}

  显示设置异常状态标志位为true。

protected void clearError()

1
2
3
protected void clearError() {
trouble = false;
}

  清除异常状态标志位。

public void write(int c)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void write(int c) {
try {
synchronized (lock) {
ensureOpen();
out.write(c);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}

  向底层输出流中写入一个字符数据。通过使用synchronized关键字可以保证多线程环境下的线程安全。具体实现则是通过直接调用底层输出流的write()方法来完成写入操作。如果期间出现了IOException,那么异常不返回,设置异常状态标志位为true。

public void write(char buf[], int off, int len)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void write(char buf[], int off, int len) {
try {
synchronized (lock) {
ensureOpen();
out.write(buf, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}

public void write(char buf[]) {
write(buf, 0, buf.length);
}

  向底层输出流中写入字符数组buf中自off位置起长度为len的内容。通过使用synchronized关键字可以保证多线程环境下的线程安全。具体实现则是通过直接调用底层输出流的write(char[] cbuf, int off, int len)方法来完成写入操作。如果期间出现了IOException,那么异常不返回,设置异常状态标志位为true。

public void write(String s, int off, int len)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void write(String s, int off, int len) {
try {
synchronized (lock) {
ensureOpen();
out.write(s, off, len);
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}

public void write(String s) {
write(s, 0, s.length());
}

  向底层输出流中写入字符串s中自off位置起长度为len的内容。通过使用synchronized关键字可以保证多线程环境下的线程安全。具体实现则是通过直接调用底层输出流的write(String str, int off, int len)方法来完成写入操作。如果期间出现了IOException,那么异常不返回,设置异常状态标志位为true。

private void newLine()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void newLine() {
try {
synchronized (lock) {
ensureOpen();
out.write(lineSeparator);
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}

  另起一行写内容。如果设置了自动推送数据,那么就将当前底层输出流中含有的字符数据推送到目标输出位置。

public void print(args …)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 打印boolean值,如果值为true,那么则打印“true”,否则打印“false”
public void print(boolean b) {
write(b ? "true" : "false");
}

// 打印一个字符
public void print(char c) {
write(c);
}

// 打印一个数字
public void print(int i) {
write(String.valueOf(i));
}

// 打印一个long型数字
public void print(long l) {
write(String.valueOf(l));
}

// 打印一个单精度浮点数
public void print(float f) {
write(String.valueOf(f));
}

// 打印一个双精度浮点数
public void print(double d) {
write(String.valueOf(d));
}

// 打印一个字符数组
public void print(char s[]) {
write(s);
}

// 打印一个字符串,如果入参字符串为null,则打印“null”
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}

// 打印一个对象obj
public void print(Object obj) {
write(String.valueOf(obj));
}

public void println(args..)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 换行
public void println() {
newLine();
}

// 打印一个boolean值并换行
public void println(boolean x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个字符并换行
public void println(char x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个数字并换行
public void println(int x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个long型数字并换行
public void println(long x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个单精度浮点数值并换行
public void println(float x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个双精度浮点数值并换行
public void println(double x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个字符数组并换行
public void println(char x[]) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个字符串并换行
public void println(String x) {
synchronized (lock) {
print(x);
println();
}
}

// 打印一个对象obj并换行
public void println(Object x) {
String s = String.valueOf(x);
synchronized (lock) {
print(s);
println();
}
}

public PrintWriter printf(String format, Object … args)

1
2
3
public PrintWriter printf(String format, Object ... args) {
return format(format, args);
}

  按照format指定的格式将args中的数据内容打印输出到底层输出流中。实际调用后执行效果同方法format(String format, Object … args)

public PrintWriter format(String format, Object … args)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public PrintWriter format(String format, Object ... args) {
try {
synchronized (lock) {
ensureOpen();
if ((formatter == null)
|| (formatter.locale() != Locale.getDefault()))
formatter = new Formatter(this);
formatter.format(Locale.getDefault(), format, args);
if (autoFlush)
out.flush();
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
return this;
}

  按照format指定的格式将args中带有的内容打印输出到底层输出流中。在根据格式进行内容拼装时采用的运行机器默认的语言环境(Locale)。如果允许自动推送数据,那么就将当前底层输出流中含有的字符数据推送到目标输出位置。

public PrintWriter printf(Locale l, String format, Object … args)

1
2
3
public PrintWriter printf(Locale l, String format, Object ... args) {
return format(l, format, args);
}

  按照format指定的格式、Locale指定的语言环境将args中的数据内容打印输出到底层输出流中。实际调用后执行效果同方法format(Locale l, String format, Object … args)

public PrintWriter format(Locale l, String format, Object … args)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public PrintWriter format(Locale l, String format, Object ... args) {
try {
synchronized (lock) {
ensureOpen();
if ((formatter == null) || (formatter.locale() != l))
formatter = new Formatter(this, l);
formatter.format(l, format, args);
if (autoFlush)
out.flush();
}
} catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
} catch (IOException x) {
trouble = true;
}
return this;
}

  按照format指定的格式、Locale指定的语言环境将args中带有的内容打印输出到底层输出流中。在根据格式进行内容拼装时采用的运行机器默认的语言环境(Locale)。如果允许自动推送数据,那么就将当前底层输出流中含有的字符数据推送到目标输出位置。

public PrintWriter append(CharSequence csq)

1
2
3
4
5
6
7
public PrintWriter append(CharSequence csq) {
if (csq == null)
write("null");
else
write(csq.toString());
return this;
}

  将CharSequence对象中含有的内容追加输出到底层输出流中。实际调用后执行效果同方法write(String s)

public PrintWriter append(CharSequence csq, int start, int end)

1
2
3
4
5
public PrintWriter append(CharSequence csq, int start, int end) {
CharSequence cs = (csq == null ? "null" : csq);
write(cs.subSequence(start, end).toString());
return this;
}

  将CharSequence对象中自start至end之间的内容追加输出到底层输出流中。实际调用后执行效果同方法write(String s)

public PrintWriter append(char c)

1
2
3
4
public PrintWriter append(char c) {
write(c);
return this;
}

  将入参字符c追加输出到底层输出流中。实际调用后执行效果同方法write(int c)

public void flush()

1
2
3
4
5
6
7
8
9
10
public void flush() {
try {
synchronized (lock) {
ensureOpen();
out.flush();
}
} catch (IOException x) {
trouble = true;
}
}

  将当前输出流中存储的数据推送到目标输出位置。通过使用synchronized关键字保证了多线程环境下的线程安全。在底层输出流开启的情况下通过调用底层输出流的flush()方法将数据推送到输出流指定的目标输出位置。如果在过程中出现了异常,当前方法不会向上抛出异常,而是将trouble字段标记为true,通过checkError()方法了解当前方法是否出现了异常。

public void close()

1
2
3
4
5
6
7
8
9
10
11
12
public void close() {
try {
synchronized (lock) {
if (out == null)
return;
out.close();
out = null;
}
} catch (IOException x) {
trouble = true;
}
}

  关闭当前输出流。通过使用synchronized关键字保证了多线程环境下的线程安全。如果底层输出流已经关闭,那么直接返回,否则通过调用底层输出流的close()方法关闭底层输出流并释放占用的相关资源。如果在过程中出现了异常,当前方法不会向上抛出异常,而是将trouble字段标记为true,通过checkError()方法了解当前方法是否出现了异常。

涉及基础知识点

  1. NIL

参考文献

  1. NIL




------------- End of this article, thanks! -------------


  版权声明:本文由N.C.Lee创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,转载请注明作者及出处。
  本文作者为 N.C.Lee
  本文标题为 Java I/O 21 - PrintWriter
  本文链接为 https://marcuseddie.github.io/2018/java-PrintWriter.html