IO第十回:处理流之三:打印流
标签: IO流
什么是打印流
在整个 IO 包中,打印流是输出信息最方便的类,主要包含字节打印流(PrintStream) 和字符打印流(PrintWriter) 。
打印流提供了非常方便的打印功能,可以打印任何的数据类型,例如: 小数、整数、字符串等等。
只有输出流才有打印流:PrintWriter和PrintStream分别针对字符和字节,提供了重载的print,println方法用于多种数据类型的输出。PrintWriter和PrintStream操作不会抛出异常,数据没打印出来也不会抛异常。
字节打印流:PrintStream
什么是PrintStream
public class PrintStream extends FilterOutputStream implements Appendable, CloseableA
PrintStream 是字节打印输出流,是处理流的一种,对其他输出流进行处理,为其添加了功能,使它们能够方便地打印各种数据值表示形式。
与其他输出流不同,PrintStream 永远不会抛出 IOException;
它产生的IOException会被自身的函数所捕获并设置错误标记, 用户可以通过 checkError() 返回错误标记,从而查看PrintStream内部是否产生了IOException。
另外,PrintStream 提供了自动flush 和 字符集设置功能。所谓自动flush,就是往PrintStream写入的数据会立刻调用flush()函数。
为什么要使用PrintStream
节点流的不便之处
在节点流中,我们使用字节输出流FileOutputStream
和字符输出流FileWriter
,但是这样有些不方便,我们以字节输出流FileOutputStream
为例,我们来看它的write方法:
void write(byte[] b) //将 b.length个字节从指定的字节数组写入此文件输出流。
void write(byte[] b, int off, int len) //将 len字节从位于偏移量off的指定字节数组写入此文件输出流。
void write(int b) //将指定的字节写入此文件输出流。
我们知道,FileOutputStream
的write()所接受的参数,都是字节,要么是byte数组,要么是int类型的ASCII码值代表的字节。那么我们想要输出其他类型的东西时,就会有很多不便!例如:.write(new String(“I am Japson.”).getBytes());
我想输出数字“97”,如果我用以下的代码,就是错误的
File file = new File("F:\\a.txt");
FileOutputStream outputStream = new FileOutputStream(file,true);
outputStream.write(97);
那么代码执行完之后,a.txt中的内容不是97
,而是a
,因为write方法接收的为byte类型的数据,97对应的ASCII码为a。
正确的做法是:
File file = new File("F:\\a.txt");
FileOutputStream outputStream = new FileOutputStream(file,true);
outputStream.write("97".getBytes()); //先将97作为字符串再转换为byte数组
outputStream.write(new String("I am Japson.").getBytes());
//创建一个字符串对象并使用String类的getBytes()方法
缓冲流PrintStream的好处
PrintStream得出现,使的我们将数据写入文件变得十分方便,参数中传入的是什么类型的数据,就会给写入什么类型的数据。原因是他内部帮我们转换好了。
File file = new File("PrintStream.txt");
FileOutputStream fos = new FileOutputStream(file);
ps = new PrintStream(fos,true);
ps.println(123);
ps.println('a');
ps.println("Hello");
ps.println(3.14159);
ps.println(true);
不管什么数据类型,都会转换为字符串,甚至是对象也不例外。
构造方法
PrintStream构造方法可以接收File对象,OutputStream对象,String类型的文件名,这些是将要进行打印的内容所打印到的地方。
PrintStream(File file)
创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用默认字符集。PrintStream(File file, String CharSetName)
创建fileName对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用charsetName字符集。PrintStream(OutputStream out)
将“输出流OutputStream”作为PrintStream的输出流,不会自动flush,并且采用默认字符集。PrintStream(OutputStream out, boolean autoFlush)
将“输出流out”作为PrintStream的输出流,当autoFlush为true时,每当写入一个字节数组则会会自动flush。PrintStream(OutputStream out, boolean autoFlush, String encoding)
创建file对应的FileOutputStream,然后将该FileOutputStream作为PrintStream的输出流,不自动flush,采用encoding字符集。PrintStream(String fileName)
使用指定的文件名创建新的打印流,无需自动换行。PrintStream(String fileName, String csn)
创建一个新的打印流,不需要自动换行,具有指定的文件名和字符集。
格式化输出
在JDK1.5以后,对PrintStream进行了扩充,增加了格式化的输出方式,直接使用printf()方法就能直接进行操作。但是在格式化输出的时候要指定输出类型。
字符 | 描述 |
---|---|
%s | 表示内容为字符串 |
%d | 表示内容为整数 |
%f | 表示内容为小数 |
%c | 表示内容为字符 |
以下是java.io.PrintStream.printf()方法声明
public PrintStream printf(String format,Object... args)
format
– 格式字符串在格式字符串的语法描述
args
– 参数的格式说明符在格式字符串中引用。如果有多于格式说明符的参数,多余的参数被忽略。参数的个数是可变的,并且可以为零。参数的最大数量受到Java数组的最大维数的Java虚拟机规范定义的限制。上一个null参数的行为取决于转换。
这个方法返回当前输出流
例子:
public class PrintDemo02{
public static void main(String arg[]) throws Exception{
PrintStream ps = null ; // 声明打印流对象
// 如果现在是使用FileOuputStream实例化,意味着所有的输出是向文件之中
ps = new PrintStream(new FileOutputStream(new File("d:" + File.separator + "test.txt"))) ;
String name = "Japson" ; // 定义字符串
int age = 18 ; // 定义整数
float score = 990.356f ; // 定义小数
char sex = 'M' ; // 定义字符
ps.printf("姓名:%s;年龄:%d;成绩:%f;性别:%c",name,age,score,sex) ;
ps.close() ;
}
};
在printf中,%s,%d等代表各自定义的内容
输出为:
姓名:Japson;年龄:18;成绩:990.356;性别:M
方法摘要
PrintStream append(char c)
将指定的字符附加到此输出流。boolean checkError()
刷新流并检查其错误状态。protected void clearError()
清除此流的内部错误状态。void close()
关闭流。void flush()
刷新流。PrintStream format(Locale l, String format, Object… args)
使用指定的格式字符串和参数将格式化的字符串写入此输出流。void print(boolean b)
打印b的值,此函数有很多重载方法PrintStream printf(Locale l, String format, Object… args)
使用指定的格式字符串和参数将格式化的字符串写入此输出流的便利方法。void println()
通过写入行分隔符字符串来终止当前行,此函数有很多重载方法。protected void setError()
将流的错误状态设置为 true 。void write(byte[] buf, int off, int len)
从指定的字节数组写入 len个字节,从偏移 off开始到此流。void write(int b)
将指定的字节写入此流。
例子
package charIO;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* Created by japson on 8/26/2017.
*/
public class PrintDemo {
public static void printStream() {
PrintStream ps = null;
try {
File file = new File("PrintStream.txt");
FileOutputStream fos = new FileOutputStream(file);
ps = new PrintStream(fos,true);
ps.println("123");
ps.println("abc");
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
ps.close();
}
}
public static void main(String[] args) {
printStream();
}
}
结果是在工程目录下新建一个PrintStream.txt文件,然后将”123”和”abc”打印到文件里。
字符打印流
什么是PrintWriter
IO包中提供了一个与PrintStream对应的PrintWriter类。PrintWriter 是字符类型的打印输出流,它继承于Writer。
PrintStream 用于向文本输出流打印对象的格式化表示形式。它实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。
与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。
此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用 checkError() 是否出现错误。
字符打印流和字节打印流大体上差不多,因此我们看其中的区别
PrintStream 和PrintWriter区别
两个类的功能基本相同,PrintStream能做的PrintWriter也都能实现,并且PrintWriter的功能更为强大。但是由于PrintWriter出现的比较晚,较早的System.out使用的是PrintStream来实现的,所以为了兼容就没有废弃PrintStream。
PrintStream主要操作字节流,也就是说打印出来所有字符按照平台的编码转换为字节,所以一般用于二进制文件。(文本文件也是可以的)
字符串转换为字节流是平台相关的,也就是说不同的系统或者环境,可能对于同一份字符串使用PrintStream输出字节流会有差异不能够跨平台。
PrintWriter主要操作字符,可以创建指定的字符集,一般用来读取文本文件,因为默认用unicode编码,所以PrintWriter的跨平台性要比PrintStream好,也就是说PrintWriter可用于操作中文。
在自动刷新方面:
PrintStream在遇到换行符的时候就会自动刷新,即在调用了println()方法,或者文本中出现“\n”,就会自动flush
PrintWriter则不会,要在构造方法中设置自动刷新,或者手动flush。