承接上文,继续小小总结一下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]
哎,终于结束了