JAVA语言之JavaIO流 Part.8打印字符输出流讲解
小标 2019-01-09 来源 : 阅读 916 评论 0

摘要:本文主要向大家介绍了JAVA语言之JavaIO流 Part.8打印字符输出流讲解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言之JavaIO流 Part.8打印字符输出流讲解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

Java基础学习之JavaIO流 Part.8打印字符输出流讲解 PrintWriter 概述

PrintWriter缓冲字符数组输出流,继承了所有字符输出流的超类Writer类,用于向文本对象输入字符内容

很明显是一个处理流 用于处理字符数据 代理真正的节点流输出到数据汇 是一个非常实用的输出流

系统的System.out方法就是调用了内置的PrintWriter流

官方注释

格式化打印对象到文本输出流。本类实现了所有PrintStream也包含的方法。

但本类不包含写入字节流的方法,写入字节流可以使用无编码字节流。

与PrintStream不同,只有代理println,printf,format方法时且自动刷新

是启用状态,才会起效,而不是在一个新的换行符被输出时进行自动刷新。

这些方法使用平台自己的换行符而不是普通的换行符

此类的所有方法不会跑出I/O异常,除了其中的一些构造方法。

终端可以查询是否是一些代理方法抛出的受检异常

源码分析 成员属性代理的节点输出流
protected Writer out;
是否自动刷新
private final boolean autoFlush;
是否有抛出异常 官方注释提到PrintWriter不抛出异常
所以如果发生异常只是 此标志位置为false
private boolean trouble = false;
格式化参数
private Formatter formatter;
输出流 适配器模式
private PrintStream psOut = null;
成员方法

构造方法

创建一个不会自动刷新的PrintWriter 对象
public PrintWriter (Writer out) {
       this(out, false);
   }

创建一个PrintWriter 对象,并设置是否自动刷新
如果自动刷新则 println,printf,format方法将会自动刷新输出流
public PrintWriter(Writer out,
                  boolean autoFlush) {
   super(out);
   this.out = out;
   this.autoFlush = autoFlush;
}

创建一个不会自动刷新的PrintWriter对象
调用OutputStream作为真正的输出节点流
可以看到此方法和第一个方法的不同之处就是入参是OutputStream
内部调用了下面的方法
public PrintWriter(OutputStream out) {
   this(out, false);
}

创建一个PrintWriter对象,并设置是否自动刷新
调用缓冲流包裹的OutputStreamWriter转换器对象输出到真正的节点流中
编码采用默认字符集
public PrintWriter(OutputStream out, boolean autoFlush) {
   this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);

   // 为了传播异常内容 保存输出流
   if (out instanceof java.io.PrintStream) {
       psOut = (PrintStream) out;
   }
}

创建一个PrintWriter对象输出数据到指定文件名的文件,并不自动刷新
内部调用缓冲流包裹的OutputStreamWriter转换器对象输出到真正的文件输出节点流中
内部调用了上面的第二个构造方法
public PrintWriter(String fileName) throws FileNotFoundException {
   this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
        false);
}

创建一个PrintWriter对象输出数据到指定文件名的文件,并不自动刷新,
根据编码名使用指定的编码方式
内部调用了下面的私有构造方法
public PrintWriter(String fileName, String csn)
   throws FileNotFoundException, UnsupportedEncodingException
{
   this(toCharset(csn), new File(fileName));
}

私有构造方法
内部使用缓冲流包裹的OutputStreamWriter转换器对象输出到真正的文件输出节点流中
并根据charset字符集指定编码方式
private PrintWriter(Charset charset, File file)
   throws FileNotFoundException
{
   this(new BufferedWriter(new OutputStreamWriter(
   new FileOutputStream(file), charset)),
        false);
}

创建一个PrintWriter对象输出数据到指定文件对象,并不自动刷新
public PrintWriter(File file) throws FileNotFoundException {
   this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
        false);
}

创建一个PrintWriter对象输出数据到指定文件对象,并不自动刷新
且使用指定的编码字符集
public PrintWriter(File file, String csn)
       throws FileNotFoundException, UnsupportedEncodingException
   {
       this(toCharset(csn), file);
   }

其他

确认流是否打开
private void ensureOpen() throws IOException {
   if (out == null)
       throw new IOException("Stream closed");
}

刷新流内容方法
内部捕捉了IOException
所以PrintWriter不会抛出IOException
只会改变成员属性troubled的标志位
public void flush() {
   try {
       synchronized (lock) {
           ensureOpen();
           out.flush();
       }
   }
   catch (IOException x) {
       trouble = true;
   }
}

检查流错误方法
同时刷新流内容,返回错误标志位
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() {
       trouble = true;
   }
清除错误标志位方法
protected void clearError() {
   trouble = false;
}

写入数据方法
这是一个阻塞方法 并且是线程安全的
所以捕捉了受检异常InterruptedIOException
并重新设置了线程中断以方便上级方法检测
public void write(int c) {
   try {
       synchronized (lock) {
           ensureOpen();
           out.write(c);
       }
   }
   catch (InterruptedIOException x) {
       Thread.currentThread().interrupt();
   }
   catch (IOException x) {
       trouble = true;
   }
}

其他入参不同的重写写入方法 方法体大同小异
public void write(char buf[], int off, int len)
{……}

public void write(char buf[])
{……}

public void write(String s, int off, int len)
{……}

新一行方法 调用println换行实际上调用的就是此方法
实际上是写入了对应系统的换行符System.lineSeparator()
private void newLine() {
   try {
       synchronized (lock) {
           ensureOpen();
           out.write(System.lineSeparator());
           if (autoFlush)
               out.flush();
       }
   }
   catch (InterruptedIOException x) {
       Thread.currentThread().interrupt();
   }
   catch (IOException x) {
       trouble = true;
   }
}

打印输出方法 入参是布尔型
然而实际上输出时是转换为了字符型了
并且采用的是默认编码
public void print(boolean b) {
   write(String.valueOf(b));
}

其他重载的打印输出方法 大同小异
我们平时调用的系统print方法就是这些方法
不是字符型的全部被转为字符型输出了
public void print(boolean b) {
   this.write(String.valueOf(b));
}

public void print(char c) {
   this.write(c);
}

public void print(int i) {
   this.write(String.valueOf(i));
}

public void print(long l) {
   this.write(String.valueOf(l));
}

public void print(float f) {
   this.write(String.valueOf(f));
}

public void print(double d) {
   this.write(String.valueOf(d));
}

public void print(char[] s) {
   this.write(s);
}

public void print(String s) {
   this.write(String.valueOf(s));
}

public void print(Object obj) {
   this.write(String.valueOf(obj));
}

打印输出并换行方法
其实就是输出完后 追加调用了println(newline)方法
public void println(boolean x) {
   Object var2 = this.lock;
   synchronized(this.lock) {
       this.print(x);
       this.println();
   }
}
重载的都大同小异
public void println(char x)

public void println(int x)

public void println(long x)

public void println(float x)

public void println(double x)

public void println(char[] x)

字符格式化打印输出方法
入参是格式化参数format 和被格式化的字符内容 是个可变数组Object ... args
字符内容和格式化参数不必一一对应 但不能字符内容少于格式化参数
具体可以看printf的详解
此方法内部调用的是format方法
public PrintWriter printf(String format, Object ... args) {
   return format(format, args);
}

格式化打印方法 String format为格式化参数  可变数组Object ... args为需要格式化的字符内容
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;
}

增加了一个可指定字符区位Locale的参数 可以根据指定的区位习惯的格式进行输出
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;
}

追加打印方法
public PrintWriter append(CharSequence csq) {
       write(String.valueOf(csq));
       return this;
   }

追加打印方法 打印字符或字符序列到输出流中
和print方法不同的是返回了本身PrintWriter 对象
可以链式调用
public PrintWriter append(CharSequence csq, int start, int end) {
   if (csq == null) csq = "null";
   return append(csq.subSequence(start, end));
}

public PrintWriter append(char c) {
   write(c);
   return this;
}
代码示例

构造一个PrintWriter 对象 并使用write方法输出 必须手动flush

   char[] chars={'爱', '吃', '拉', '面', '的','小','泉','同','学' };
   String str="爱吃拉面的小泉同学";
   File file=new File("d:\\animation.txt");
   PrintWriter pw=new PrintWriter(new FileOutputStream(file));
   pw.write(chars);
   pw.write(str);
   pw.flush();

   PrintWriter pw2=new PrintWriter("d:\\animation2.txt");
   pw2.write("王牌御史");
   pw2.flush();

运行结果

       爱吃拉面的小泉同学爱吃拉面的小泉同学

       王牌御史

使用print方法输出

   PrintWriter pw = new PrintWriter("d:\\pw.txt");

   pw.println("这是一个换行输出");
   // 将字符'A'对应ASCII码写入到输出流中,等于输出'A'
   pw.write(0x41);
   // 将字符串"65"写入到输出流中。
   pw.append('B').append("CDEF");
   pw.println();

   String str = "今天是";
   int mouth=5;
   int day=1;
   pw.printf("%s%d.%d", str, mouth,day);
   pw.flush();

运行结果

这是一个换行输出
ABCDEF
今天是5.1

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程