PrintWriter
1、 类功能简介:
打印字符流、用于将各种java数据一字符串的形式打印到底层字符输出流中、本身不会产生任何IOException、但是可以通过他的一个方法来查看是否抛出异常、可以指定autoFlush、若为true则当调用newLine、println、format方法时都会自动刷新、即将底层字符输出流out中的字符flush到目的地中。对PrintWriter有许多构造方法、和一般方法、但是这些方法都有个核心方法、构造方法:一个是传入字符流时的构造方法PrintWriter(Writer out, autoFlush)、一个是传入字节流时的构造方法PrintWriter(OutputStream out, boolean autoFlush)、一般方法:一个是write(char[] cbuf, int off, int len)、一个是write(String, int off, int len);
2、PrintWriter API简介:
A:关键字
- protected Writer out; 传入的底层字符输出流
- private boolean autoFlush = false; 是否自动刷新
- private boolean trouble = false; 是否抛异常
- private Formatter formatter; 格式化类
- private PrintStream psOut = null; 字节打印流、用于checkError方法
B:构造方法
- PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。
- PrintWriter(File file, String csn) 创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
- PrintWriter(OutputStream out 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
- PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。
- PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
- PrintWriter(String fileName, String csn) 创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
- PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
- PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。
C:一般方法
- PrintWriter append(char c) 将指定字符添加到此 writer。
- PrintWriter append(CharSequence csq) 将指定的字符序列添加到此 writer。
- PrintWriter append(CharSequence csq, int start, int end) 将指定字符序列的子序列添加到此 writer。
- boolean checkError() 如果流没有关闭,则刷新流且检查其错误状态。
- protected void clearError() 清除此流的错误状态。
- void close() 关闭该流并释放与之关联的所有系统资源。
- void flush() 刷新该流的缓冲。
- PrintWriter format(Locale l, String format, Object... args) 使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。
- PrintWriter format(String format, Object... args) 使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。
- void print(boolean b) 打印 boolean 值。
- void print(char c) 打印字符。
- void print(char[] s) 打印字符数组。
- void print(double d) 打印 double 精度浮点数。
- void print(float f) 打印一个浮点数。
- void print(int i) 打印整数。
- void print(long l) 打印 long 整数。
- void print(Object obj) 打印对象。
- void print(String s) 打印字符串。
- PrintWriter printf(Locale l, String format, Object... args) 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。
- PrintWriter printf(String format, Object... args) 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。
- void println() 通过写入行分隔符字符串终止当前行。
- void println(boolean x) 打印 boolean 值,然后终止该行。
- void println(char x) 打印字符,然后终止该行。
- void println(char[] x) 打印字符数组,然后终止该行。
- void println(double x) 打印双精度浮点数,然后终止该行。
- void println(float x) 打印浮点数,然后终止该行。
- void println(int x) 打印整数,然后终止该行。
- void println(long x) 打印 long 整数,然后终止该行。
- void println(Object x) 打印 Object,然后终止该行。
- void println(String x) 打印 String,然后终止该行。
- protected void setError() 指示已发生错误。
- void write(char[] buf) 写入字符数组。
- void write(char[] buf, int off, int len) 写入字符数组的某一部分。
- void write(int c) 写入单个字符。
- void write(String s) 写入字符串。
- void write(String s, int off, int len) 写入字符串的某一部分。
3、源码分析
- package com.chy.io.original.code;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InterruptedIOException;
- import java.io.UnsupportedEncodingException;
- import java.util.Formatter;
- import java.util.IllegalFormatException;
- import java.util.Locale;
- /**
- *
- * @version 1.1, 13/11/17
- * @author andyChen
- */
- public class PrintWriter extends Writer {
- /**
- * 被PrintWriter装饰的底层Writer、OutputStream实现类out
- */
- protected Writer out;
- //是否自动刷新
- private boolean autoFlush = false;
- //是否抛异常
- private boolean trouble = false;
- //格式化类
- private Formatter formatter;
- //字节打印流、用于checkError方法
- private PrintStream psOut = null;
- /**
- * 换行符
- */
- private String lineSeparator;
- /**
- * 根据传入的Writer实现类out创建PrintWriter、不具有自动flush功能。
- */
- public PrintWriter (Writer out) {
- this(out, false);
- }
- /**
- * 创建PrintWriter、指定autoFlush、并且根据平台不同初始化linSeparator
- */
- public PrintWriter(Writer out,
- boolean autoFlush) {
- super(out);
- this.out = out;
- this.autoFlush = autoFlush;
- lineSeparator = (String) java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("line.separator"));
- }
- /**
- * 根据OutputStream out创建PrintWriter。不具有自动flush功能。
- */
- public PrintWriter(OutputStream out) {
- this(out, false);
- }
- /**
- * 根据底层OutputStream out创建pw、指定是否具有autoFlush功能。
- * 本质只是将out转换成writer、然后为其添加缓冲功能、再用PrintWriter装饰一下。
- * 如果传入的是PrintStream、则赋给全局变量psOut
- */
- 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 = (java.io.PrintStream) out;
- }
- }
- /**
- * 根据传入的文件名构造不具有自动flush功能的PrintWriter。
- * 本质还是根据文件名创建文件字节输出流out、再将out转换成writer、对其添加缓冲功能、最后用pw装饰。
- */
- public PrintWriter(String fileName) throws FileNotFoundException {
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
- false);
- }
- /**
- * 与上面一样、只是多了一个可以使用指定编码读取的功能。
- */
- public PrintWriter(String fileName, String csn)
- throws FileNotFoundException, UnsupportedEncodingException
- {
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
- false);
- }
- /**
- * 根据传入的文件构造不具有自动flush功能的PrintWriter。
- * 本质还是根据文件名创建文件字节输出流out、再将out转换成writer、对其添加缓冲功能、最后用pw装饰。
- */
- public PrintWriter(File file) throws FileNotFoundException {
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
- false);
- }
- /**
- * 与上面一样、只是多了一个可以使用指定编码读取的功能。
- */
- public PrintWriter(File file, String csn)
- throws FileNotFoundException, UnsupportedEncodingException
- {
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
- false);
- }
- /** 检测底层流是否关闭 */
- private void ensureOpen() throws IOException {
- if (out == null)
- throw new IOException("Stream closed");
- }
- /**
- * flush底层流
- */
- public void flush() {
- try {
- synchronized (lock) {
- ensureOpen();
- out.flush();
- }
- }
- catch (IOException x) {
- trouble = true;
- }
- }
- /**
- * 关闭此流、释放与此流有关的所有资源
- */
- public void close() {
- try {
- synchronized (lock) {
- if (out == null)
- return;
- out.close();
- out = null;
- }
- }
- catch (IOException x) {
- trouble = true;
- }
- }
- /**
- * 同PrintStream一样、不会抛出IO异常、出现异常时只会自己内部消化掉、
- * 可以通过此方法来查看print过程中是否有异常出现。
- */
- 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;
- }
- /**
- * 可以显示的设置print产生异常。
- */
- protected void setError() {
- trouble = true;
- }
- /**
- * 清除异常信息
- */
- protected void clearError() {
- trouble = false;
- }
- /**
- * 写入一个字符、
- * 这里产生IOException的原因是此方法是继承自Writer
- */
- public void write(int c) {
- try {
- synchronized (lock) {
- ensureOpen();
- out.write(c);
- }
- }
- catch (InterruptedIOException x) {
- Thread.currentThread().interrupt();
- }
- catch (IOException x) {
- trouble = true;
- }
- }
- /**
- * 将从下标off开始、len个字符写入到out中。
- * 这里也许会有个疑问?当传入的out是OutputStream时还能使用
- * out.write(char[] buf, int off, int len)吗?
- * 可以:当传入OutputStream时、调用的构造方法内部会将OutputStream
- * 包装成OutputStreamWriter、同时使用BufferedWriter来封装、最后再用PrintWriter来装饰。
- * 这里的out表示的已经变成BufferedWriter。
- */
- 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;
- }
- }
- /**
- * 将一个字符数组中所有字符写入到out中
- */
- public void write(char buf[]) {
- write(buf, 0, buf.length);
- }
- /**
- * 将s的一部分写入out中
- */
- 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;
- }
- }
- /**
- * 将String写入out中
- */
- public void write(String s) {
- write(s, 0, s.length());
- }
- /**
- * 将一个换行符写入out中、如果设置了自动刷新、则刷新out。
- */
- 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;
- }
- }
- /**
- * 将一个boolean写入out中、不管有没有设置autoFlush、都不会自动flush
- */
- public void print(boolean b) {
- write(b ? "true" : "false");
- }
- /**
- * 将一个char写入out中、
- */
- public void print(char c) {
- write(c);
- }
- /**
- * 将一个int写入out中、
- */
- public void print(int i) {
- write(String.valueOf(i));
- }
- /**
- * 将一个long写入out中、
- */
- public void print(long l) {
- write(String.valueOf(l));
- }
- /**
- * 将一个float写入out中、 rinted
- */
- public void print(float f) {
- write(String.valueOf(f));
- }
- /**
- * 将一个double写入out中、
- */
- public void print(double d) {
- write(String.valueOf(d));
- }
- /**
- *将一个char[]写入out中、
- */
- public void print(char s[]) {
- write(s);
- }
- /**
- * 将一个String写入out中、
- */
- public void print(String s) {
- if (s == null) {
- s = "null";
- }
- write(s);
- }
- /**
- * 将一个Object写入out中、
- */
- public void print(Object obj) {
- write(String.valueOf(obj));
- }
- /* Methods that do terminate lines */
- /**
- * 将一个换行符写入out中、
- */
- public void println() {
- newLine();
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(boolean x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(char x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(int x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(long x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(float x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(double x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(char x[]) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(String x) {
- synchronized (lock) {
- print(x);
- println();
- }
- }
- /**
- * 将一个换行符写入out中、
- */
- public void println(Object x) {
- String s = String.valueOf(x);
- synchronized (lock) {
- print(s);
- println();
- }
- }
- /**
- * 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。
- */
- public PrintWriter printf(String format, Object ... args) {
- return format(format, args);
- }
- /**
- * 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。
- */
- public PrintWriter printf(Locale l, String format, Object ... args) {
- return format(l, format, args);
- }
- /**
- *使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。
- */
- 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;
- }
- /**
- *使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。
- */
- 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;
- }
- /**
- * 将一个有序字符序列追加到out中
- */
- public PrintWriter append(CharSequence csq) {
- if (csq == null)
- write("null");
- else
- write(csq.toString());
- return this;
- }
- /**
- * 将一个有序字符序列一部分追加到out中
- */
- public PrintWriter append(CharSequence csq, int start, int end) {
- CharSequence cs = (csq == null ? "null" : csq);
- write(cs.subSequence(start, end).toString());
- return this;
- }
- /**
- * 将一个字符追加到out中
- */
- public PrintWriter append(char c) {
- write(c);
- return this;
- }
- }
4、实例演示:
- package com.chy.io.original.test;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
- import com.chy.io.original.code.FileWriter;
- import com.chy.io.original.utils.StudentDTO;
- @SuppressWarnings("all")
- public class PrintWriterTest {
- private final static String fileName = "D:\\pw.txt";
- private final static File file = new File(fileName);
- private final static String targetStr = "马心心";
- public static void showPrintWriterconstructor() throws IOException{
- //下面这一组个构造方法效果一样、使用默认编码
- PrintWriter pw1 = new PrintWriter(new FileWriter(file));
- PrintWriter pw2 = new PrintWriter(new FileWriter(fileName));
- PrintWriter pw3 = new PrintWriter(file);
- PrintWriter pw4 = new PrintWriter(fileName);
- //下面这组构造方法效果一样、具有自动刷新功能
- PrintWriter pw5 = new PrintWriter(new FileWriter(file), true);
- PrintWriter pw6 = new PrintWriter(new FileWriter(fileName), true);
- PrintWriter pw7 = new PrintWriter(new FileOutputStream(file), true);
- PrintWriter pw8 = new PrintWriter(new FileOutputStream(fileName), true);
- //下面这一组构造方法效果一样、使用指定的GBK编码
- PrintWriter pw9 = new PrintWriter(file, "GBK");
- PrintWriter pw10 = new PrintWriter(fileName, "GBK");
- }
- /**
- * 这里只测试一下向文件流中打印一个中文字符串、然后读取出来查看乱码情况、
- * 和写入一个Object对象、再读取出来以字符串的形式打印出来。
- */
- public static void testPrintWriterDefault() throws IOException{
- PrintWriter pw = new PrintWriter(file);
- pw.println(targetStr);
- StudentDTO student = new StudentDTO(1,"陈华应");
- pw.println(student);
- pw.close();
- BufferedReader br = new BufferedReader(new java.io.FileReader(file));
- String str;
- while((str = br.readLine()) != null){
- System.out.println(str);
- }
- br.close();
- }
- /**
- * 构造打印流时使用指定GBK编码
- * @throws IOException
- */
- public static void testPrintWriterGBK() throws IOException{
- PrintWriter pw = new PrintWriter(file, "GBK");
- pw.println(targetStr);
- StudentDTO student = new StudentDTO(1,"陈华应");
- pw.println(student);
- pw.close();
- BufferedReader br = new BufferedReader(new java.io.FileReader(file));
- String str;
- while((str = br.readLine()) != null){
- System.out.println(str);
- }
- br.close();
- }
- public static void main(String[] args) throws IOException {
- //testPrintWriterDefault();
- testPrintWriterGBK();
- }
- }
总结:
PrintWriter与PrintStream很类似、要注意的就是一个是自动刷新的问题、另一个就是PrintStream可以实现将字节写入底层流中write(intb) write(byte[] b, int off, int len)、而PrintWriter没有相关方法来直接将字节写入到out中、还有一点就不管是PrintWriter还是PrintStream、他写入到底层流中的java基础类型或者java对象都是以字符串的形式写入的、所以当我们读取之后要做一些处理、而关于print(Object)只是将Object的表示此对象的Object.toString()这个结果写入到out中、所以读取出来并不是强转一下就可以使用、要想操作java基础类型和对象、应该使用对应的流DataInputStream/DataOutputStream ObjectInputStream/ObjectOutputStream。