承接上文,继续小小总结一下IO流。

上文主要总结了一下IO流中的基本流,下面主要总结一下IO流中的包装流/高级流

现在假设我想我文本中输入小数,该怎么办呢?用上面的方式无效。那么现在介绍一下:

包装流/高级流:

(1)DataInputStream/DataOutputStream:数据流

(2)BufferedInputStream/BufferedOutputStream:缓冲流

(1)我们用DataInputStream/DataOutputStream:解决上述问题

我们还是看下面一段代码:主要完成向d:/c.txt文本中写入小数3.14和汉字“中国”,如果d盘没有c.txt则先创建文件在写入,之后从该文本中读出相应数据

import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestDISDOS {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream(new File("d:\\c.txt"));
DataOutputStream dos = new DataOutputStream(fos);
dos.writeDouble(3.14);
dos.writeUTF("中国");
FileInputStream fis = new FileInputStream(new File("d:\\c.txt"));
DataInputStream dis = new DataInputStream(fis);
double d = dis.readDouble();
String s = dis.readUTF();
System.out.println(d);
System.out.println(s);
// 如何快速写小数
//      BufferedOutputStream/DataOutputStream/FileOutputStream在上面已经陈述过该等价关系
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(new File("d:\\c.txt"))));
out.writeDouble(3.1415);
// 对于包装流,关闭时候只关闭外层流就可以了,外层流中有对内层流的关闭。
dos.close();
dis.close();
out.close();
}
}

(2)现在我想将一个文件复制一个副本,用上面方法不能说不能实现,只是比较麻烦,效率也很低,那该怎么办呢?于是引出了包装流中的BufferedInputStream/BufferedOutputStream

还是以代码的形式呈现:完成将d:/src.rar复制一份并且以文件名为desc.rar存放

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestBISBOS {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream(new File("d:\\src.rar"));
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(new File("d:\\dest.rar"));
BufferedOutputStream bos = new BufferedOutputStream(fos);
int i = 0;
//bis.read()==-1代表已经读到末尾
while((i=bis.read())!=-1){
bos.write(i);
// flush不要放在循环中,不然没意义,相当于一个字节一个字节的写。
//          bos.flush();// 冲刷缓冲区,强制将缓冲区中的内容写入文件
}
// 如果缓冲区满了,自动写入文件
bos.flush();// 冲刷缓冲区,强制将缓冲区中的内容写入文件
bos.close();// close关闭之前,先flush。
}
}

现在又有新问题了。我想存入的不仅仅是简单的字节或者double类型的数据,而是一个Person类对象该如何是好呢?应运而生的产生了对象流(1)ObjectOutputStream/ObjectInputStream

有一下代码先创建一个Person类有姓名和年龄两个属性,注意这里用到了对象序列化。

对象序列化:就是把对象变成二进制或文本

Person

import java.io.Serializable;
public class Person implements Serializable{//这里需要实现序列化接口
private String name;
private int age;
public Person() {
super();
}
public String getName() {
return name;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}

还有一个测试类TestOISOOS

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import practice.Person;
public class TestOISOOS {
public static void main(String[] args) throws Exception {
File file = new File("d:\\person.data");
// 输出流新建文件
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
//创建Person对象p1
Person p1 = new Person("zhangfei",23);
//对象写入现在可以查看d盘下多了一个peison.data文件
oos.writeObject(p1);//对象序列化
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
//对象读出,用Person对象接受
Person p2 = (Person) ois.readObject();//对象反序列化
System.out.println(p2);
ois.close();
oos.close();
}
}

输出结果:

Person [name=zhangfei, age=23]

(2)上面代码用到了对象序列化,但只是单个对象的序列化,那么如何实现多个对象的序列化呢?请看下面代码还是要借助Person

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class TestSer {
public static void main(String[] args) throws Exception {
Person p1 = new Person("zhangfei",20);
Person p2 = new Person("guanyu",30);
File file = new File("d:\\person.data");
// 输出流新建文件
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(p1);// 对象序列化
oos.writeObject(p2);
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
// 不建议使用这种方式序列化多个对象,while中死循环,通过break跳出
while(true){
try {
Person p = (Person) ois.readObject();// 对象反序列化
System.out.println(p);
} catch (EOFException e) {
System.out.println("读到了文件的末尾");
break;
}
}

输出结果:

Person [name=zhangfei,age=20]

Person [name=guanyu,age=30]

读到了文件的末尾

对于多个对象的序列化,前面也提到了不建议使用上述方法,那么我们还可以借助集合实现多个对象的序列化。请看代码。还是同上需要借助Person类,这里不再写Person类了

import java.io.*;
import java.util.*;
/**
* 利用集合完成多个对象的序列化,推荐使用这种方式。
*/
public class TestSerCol {
public static void main(String[] args) throws Exception {
File file = new File("d:\\person.data");
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
List<Person> list = new ArrayList<Person>();
Person p1 = new Person("zhangfei",20);
Person p2 = new Person("guanyu",30);
list.add(p1);
list.add(p2);
// 序列化整个集合
oos.writeObject(list);
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
List<Person> perList = (List<Person>) ois.readObject();
for(Person p : perList){
System.out.println(p);
}
oos.close();
ois.close();
}
}

输出结果:

Person [name=zhangfei,age=20]

Person [name=guanyu,age=30]

哎,终于结束了