IO之处理流、打印流
-
处理流(也叫包装流)是连接已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能;如:BufferedReader、BufferedWriter
-
BufferedReader、BufferedWriter类中有对应的Reader、Writer的属性,使其可以对Reader、Writer及其任意子类进行操作
字符处理流
BufferedReader
主要用于辅助Reader及其任何子类的字符输入流,它带有缓冲区,可以先将一批数据读到内存缓冲区。后续操作就可以直接从缓冲区获取数据,而不需要每次都从数据源读取数据并进行字符编码转换,从而提高数据的读取效率。关闭处理流时,只需关闭外层流即可,底层会自动关闭;需抛出异常
-
构造方法:
-
BufferedReader(Reader in ):创建一个对象来修饰参数in指定的字符输入流;
-
BufferedReader(Reader in ,int size):创建一个对象来修饰参数in指定的字符输入流,参数size指定缓冲区的大小,单位为字符;
-
-
BufferedReader还提供了readLine()方法,该方法返回包含该行内容的字符串,但该字符串中不包含任何终止符,如果到达流末尾,返回null。该方法表示每次读取一行文本内容,遇到换行(
\n
)、回车(\r
)、或回车后直接跟着换行标记符,即认为此行已终止。
String filePath = "E:\\Desktop\\新建文本文档.txt";
//创建处理流对象,需抛出异常
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line ;//按行读取
while ((line = bufferedReader.readLine())!= null ){
System.out.println(line);
}
//关闭流,这里只需关闭BufferedReader,因为底层会自动关闭
bufferedReader.close();
BufferedWriter
主要用于辅助Writer及其任意子类的字符输出流,它带有缓冲区,可以先将一批数据写入内存缓冲区,当缓冲区满了以后,再将缓冲区的数据一次性写到字符输出流,目的是提高数据的写入效率。
-
构造方法:
-
BufferedWriter(Writer out):创建一个对象来修饰参数in指定的字符输出流;
-
BufferedWriter(Writer out,int size):创建一个对象来修饰参数in指定的字符输出流,参数size指定缓冲区的大小,单位为字符;
-
-
BufferedWriter还提供了一个新的方法newLine(),该方法用于写入一个行分隔符。行分割符字符串由系统属性line.separator定义,并且不一定是单个新行(
\n
)符;
String filePath = "e:\\z_practice\\test.txt";
//如需要以追加的方式写入,在构造器中加true;创建处理流对象,需抛出异常
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("hello111,知足常乐" + "\n");//插入换行
bufferedWriter.write("hello1,知足常乐");
bufferedWriter.newLine();//插入系统相关的换行符
bufferedWriter.write("hello2,知足常乐");
//关闭流
bufferedWriter.close();
利用BufferedReader和BufferedWriter拷贝文件,不能操作二进制文件,否则复制的文件显示损坏
字节处理流
-
BufferedInputStream和BufferedOutputStream;参考字符处理流
-
用于操作二进制文件,同时也可以操作文本文件;
对象流
-
序列化和反序列化
-
序列化就是在保存数据时,保存数据的值和数据类型;
-
反序列化就是在恢复数据时,恢复数据的值和数据类型;
-
需要让某个对象支持序列化机制,则必须让其类是可序列化的,即此类必须实现Serializable接口、Externalizable接口之一;
-
Serializable,是一个标记接口,内部没有方法
-
Externalizable,该接口有方法需要实现,一般实现标记接口
-
-
八大基本类型会自动装箱,其包装类及String类已实现Serializable
-
当使用对象流写入或读入对象时,要保证对象是序列化的,这是为了保证能把对象写入到文件,并能再把对象正确的读取回到程序中;
-
ObjectOutPutStream:对象输出流,提供序列化功能;使用writeObject(Object,obj)将obj写入到一个文件中;实现了ObjectOutPut接口、OutputStream抽象类;
-
ObjectInputStream:对象输入流,提供反序列化功能;使用readObject()读取一个对象到程序中;实现了ObjectInPu接口t、InputStream抽象类;
-
构造方法:
-
ObjectInputStream(InputStream in);
-
ObjectOutPutStream(OutputStream out);
-
-
对象流的指向应当是一个输入/出流,因此当准备将一个文件写入/读取时,首先创建一个输入/出流;
//序列化对象,数据写入文件
//序列化后,保存格式不是纯文本,根据对象的格式确定
String outPath = "e:\\z_practice\\object.txt";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outPath));//抛出异常
oos.writeInt(100);
oos.writeBoolean(true);
oos.writeChar('a');
oos.writeChars("天天向上");//字符串
oos.writeDouble(100.124);
oos.writeUTF("卷不动,躺不平");//字符串
oos.writeObject(new Dog("柯基", 3));//Dog类需实现序列化接口
oos.close();
class Dog implements Serializable {}
//反序列化,读取文件到程序
//声明需反序列化的文件
String inPath = "e:\\z_practice\\object.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(inPath));
System.out.println(ois.readInt());//读取Integer
System.out.println(ois.readBoolean());//读取Boolean
System.out.println(ois.readChar());//读取字符
//System.out.println(ois.readChar());//读取字符串
System.out.println(ois.readDouble());//读取Double
System.out.println(ois.readUTF());//读取字符串
Object dog = ois.readObject();//需抛出类型转换异常ClassNotFoundException
System.out.println(dog.toString());
//重要提醒:如果希望调用对象dog的方法,需要向下转型
//对象输出流和对象输入流同包可直接转型,不同包需要将Dog类的定义拷贝到引用的地方,或者将Dog设置为public类,并导包
Dog dog1 = (Dog)dog;
System.out.println(dog1.getName());
ois.close();//关闭对象输入流
注意事项:
-
读写顺序要一致,避免类型异常
-
序列化和反序列化的对象,必须实现serializable接口;
-
序列化的类中建议添加serialVersionUID表示当前类的序列版本信息,为了提高版本的兼容性;
-
序列化对象时,默认将里面所有属性都进行序列化,但static、transient成员除外;
-
序列化对象时,要求里面属性的类型也实现序列化接口;
-
序列化具备可继承性,即某类实现了序列化,其所有子类默认实现了序列化;
转换流
-
正常情况下,字节流可以对所有的数据进行操作,但有时候在处理一些文本时需要用到字符流。所以Java中IO流提供了两种用于将字节流转换为字符流的转换流;
-
转换流可以在一定程度上避免乱码,读取文件和写入文件时的编码要和文件的编码形式对应;
-
InputStreamReader用于将字节输入流包装为字符输入流,是Reader的子类;存在多种构造器,可以传入InputStream,指定编码方式;详见类图
-
OutputStreamWriter用于将字节输出流包装为字符输出流,是Writer的子类;同上
-
当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文乱码问题,建议将字节流转换成字符流;
-
可以在使用时指定编码格式(如:ASCII、utf-8,gbk,gb2312,ISO8859-1等);
使用:将字节(输出/输入)流包装成字符(输出/输入)流并指明编码格式,再将转换流包装成对象流;
标准输入、输出流
编译类型 | 运行类型 | 默认设备 | |
---|---|---|---|
System.in | InputStream | BufferedInputStream | 键盘 |
System.out | PrintStream | PrintStream | 显示器 |
Print打印流
打印流没有输入流,只有输出流
-
PrintStream:字节流,是OutputStream的子类;
-
默认情况下,输出数据的位置是标准输出,即显示器;可以根据需求修改打印流输出的位置;
-
-
PrintWriter:字符类,是Writer的子类;具有多种构造器,详见API
//字节流
PrintStream printStream = new PrintStream("e:\\z_practice\\printStream.txt");
printStream.println("三国志7000万人");//方式一
System.setOut(new PrintStream(printStream));//方式二:修改system的默认显示器到文件
System.out.println("三国志7000万人");
printStream.close();
//字符流
PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\z_practice\\printWriter.txt"));
printWriter.write("爪哇岛");
printWriter.close();//需关闭流
Properties类
-
Properties是HashTable的子类;
-
专门用于读写配置文件的集合类;配置文件格式:键=值 键=值
-
注意:键值对不需要有空格,值不需要用引号括起来,默认是String类型;
-
Properties常用方法:
-
load:加载配置文件的键值对到Properties对象;
-
list:将数据显示到指定设备、文件、流;
-
getProperty(key):根据键获取值;
-
setProperty(key,value):设置键值对到Properties对象;有key是修改,没有是添加
-
store(writer/outputstream , null):将将Properties中的键值对存储到配置文件;在java中,保存信息到配置文件,如果含有中文,会存储为Unicode码;此处null为注解部分,可自行设置
-