天天看点

(四)IO流——对象流、打印流

对象流:

使用对象流之前,很明显需要一个自定义的对象

可是普通的自定义类创建的对象并不能被对象流序列化

我们要让这个自定义类实现一个Serializable接口(Serializable是一个标志性接口,接口中无任何内容)

例:(省略了构造方法、get/set方法、toString方法)

public class Person implements Serializable{
    private String name;
    private int age;
}
           

ObjectOutputStream(对象输出流):

对象序列化,将对象以流的形式保存到文件夹的过程

public ObjectOutputStream(OutputStream out)                             创建指定字节输出流的对象输出流对象

File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
           

void  writeObject(Object  obj)                                                                保存对象到流关联的文件中

File f = new File("b.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("jack",22);
oos.writeObject(p);
oos.close();
           

这样就完成了对象的序列化到b.txt:

(四)IO流——对象流、打印流

ObjectOutputStream对象输出流输出的对象文件就是乱码,只能用对象流查看文件内容

ObjectInputStream(对象输入流):

对象反序列化,将文件中对象以流的形式读取出来的过程

public ObjectInputStream(InputStream in)                                 创建指定字节输入流对象的对象输入流对象

File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
           

public final Object readObject ()                                                         读取一个对象 

File f = new File("b.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
System.out.println(obj);                //输出:Person{name='jack', age=22}
fis.close();
           

当保存好对象后,若对类的内容作了修改,且没有重新使用对象输出流输出一次关联文件

则readObject()方法读取到的关联文件时就会出现InvalidClassException异常

因为每次修改类内容(无论是,包括修饰符、成员变量、成员方法)都会改变类中的一个serialVersionUID值

然后再次读取该对象文件时,就会出现序列化不同的异常

若不想因为对类内容作了一些微小修改,而导致源文件不能被读取的问题

可以在类中固定好serialVersionUID值,且设置为私有final静态的!

public class Person implements Serializable{
    private String name;
    private int age;
    private static final long serialVersionUID = 12345L;        //固定serialVersionUID为任意一个值
}
           

若对象序列化时,部分成员变量中的信息,不想被writeObject写进文件中

1.可以将成员变量设置为static静态成员变量

这样改成员变量就保存在类中,创建对象时不会被对象序列化输出到文件中

public class Person implements Serializable{
    private String name;
    private int age1;
    private static final long serialVersionUID = 12345L;
    private static double high ;
}
           

弊端:设置为静态后,反序列化该对象文件确实不会显示此成员变量

可是所有Person类对象的high属性都是固定的,这样很不灵活、很不实用

2.使用transient关键字

使用该关键字修饰的成员变量,能保证成员变量的值不被序列化到文件中,只会短暂保存在内存中

public class Person implements Serializable{
    private String name;
    private int age1;
    private static final long serialVersionUID = 12345L;
    private transient int high ;            //transient修饰了high属性
}
           

做个测试:使用ObjectOutputStream输出带有transient关键字修饰的成员变量

File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person("jack",20,22);        //写入被transient关键字修饰的high属性为22
oos.writeObject(p);
oos.close();
           

然后再用ObjectInputStream查看该对象是否包含该成员变量的信息

File f = new File("a.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
Person p = (Person)obj;                     //将Object对象强转为Person对象
System.out.println(p.getHigh());            //输出:0
fis.close();
           

打印流:

PrintStream类:

public PrintStream(File file)                                                          使用指定的File对象创建打印流对象

File f = new File("b.txt");
PrintStream ps = new PrintStream(f);
           

public PrintStream(String fileName)                                           使用指定的文件名字符串创建打印流对象

PrintStream ps = new PrintStream("b.txt");
           

PrintStream类的print()和println()方法中可以输出基本数据类型

(四)IO流——对象流、打印流

其实常用System.out.println输出语句就是一个打印流的println方法

只是创建了PrintStream对象时,指定了File对象,调用print方法时输出的对象变成了文本文件

PrintStream consolePs = System.out;            //用PrintStream对象接受系统输出
PrintStream ps = new PrintStream("b.txt");
System.setOut(ps);                             //设置系统输出流为ps
System.out.println("你好");                    //这个"你好" 会打印在b.txt文本内
System.setOut(consolePs);                      //设置系统输出流为consolePs
System.out.println("你好");                    //这个"你好" 会打印在控制台