其他分享
首页 > 其他分享> > 对象流

对象流

作者:互联网

对象流的序列化,与反序列化

序列化: 把内存中的java对象保存在文件中,这个过程叫做序列化(或者叫持久化,钝化)

ObjectOutputStream

存储过程:

1、通过一些算法将这个对象的内部结构转为字节数组,包括类的类名和签名,对象的字段和数组的值以及从初始对象引用的任何其他对象的关闭。并且把字节数组保存到缓冲区

2、将表示对象的字节数组通过fos(FileOutputStream)写入到文件中

反序列化:把java对象从文件中读取到内存中,这个过程叫做反序列化(活化)

ObjectInputStream

Student类

import java.io.Serializable;//要实现这个标记型接口才可以序列化

public class Student implements Serializable {

    private int id;
    private String name;
    private int age;
    private String className;

    private char sex;

    /*
     *  添加了对象的属性  Demo06报异常
     * 1、对象类在编译的时候,编译器会为这个类产生一个serialVersionUID这个信息在类的.class文件中
     * 2、使用ObjectOutputStream去存储这个类的对象的时候会带上serialVersionUID,把它一起存入到文件中
     * 3、在ObjectInputStream去读取文件并且恢复(创建)对象的时候和文件中的serialVersionUID和当前的类的.class文件比较
     * 如果不一致会报异常InvalidClassException,一致就会创建对象
     * */
    private static final long serialVersionUID=1L;
    //给的serialVersionUID为定值,即时在写和读值之间对类的修改也不会影响对象的反序列化

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public Student() {
    }

    public Student(int id, String name, int age, String className) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.className = className;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", className='" + className + '\'' +
                '}' + "\n";
    }
}

对象输出流ObjectOutputStream:

public class Demo01 {
    /*
     * 把java对象字节输出到文件,手动打开文件会有一部分乱码
     * */
    public static void main(String[] args) {
        ObjectOutputStream oos = null;
        try {
            Student gzh = new Student(20188747, "gzh", 20, "xxxx");//创建一个对象
            FileOutputStream fos = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo01.txt");
            oos = new ObjectOutputStream(fos);

            oos.writeObject(gzh);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                oos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

对象输入流ObjectInputStream:

ObjectInputStream的作用:将保存在文件中的对象数据读取到内存中,并且重新新生成对象

/*
* 构造方法:ObjectInputStream(InputStream in)
*
* 核心方法:Object readObject()
* */
public class Demo03 {
    public static void main(String[] args) {
        ObjectInputStream ois = null;
        try {

            FileInputStream fis = new FileInputStream("C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo01.txt");
            ois = new ObjectInputStream(fis);

            Object o = ois.readObject();
            // 通过对象流创建的对象并不是调用对象的构造方法,而是JVM内部创建的对象。也是对象的深拷贝实现方式之一.
            System.out.println(o);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {

            if(ois!=null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在对存储了对象的文件进行读取之前,对对象实体类进行了修改,之后再对文件进行读取

public class Demo06 {
    /*
     * 1、对象类在编译的时候,编译器会为这个类产生一个serialVersionUID这个信息在类的.class文件中
     * 2、使用ObjectOutputStream去存储这个类的对象的时候会带上serialVersionUID,把它一起存入到文件中
     * 3、在ObjectInputStream去读取文件并且恢复(创建)对象的时候和文件中的serialVersionUID和当前的类的.class文件比较
     *    如果不一致会报异常InvalidClassException,一致就会创建对象
     * (我感觉:应该是在创建对象的时候,对象类属性发生改变,就不知道是创建文件中的对象,还是创建类中的对象,所有要设置比较serialVersionUID)
     * 在执行对象在程序与文件的读写操作的时候
     *
     * */
    //文件保存的是没有修改过的类的对象
    //在Student类中添加了属性,已经注释了,不注释运行Demo06就报异常
    //在Student类中给定serialVersionUID为定值,即时在写和读值之间对类的修改也不会影响对象的反序列化
    private static final String PATH = "C:\\Users\\GzhAnkh\\Desktop\\FileApiDemo03\\Demo04.ser";

    public static void main(String[] args) {
        ObjectInputStream ois = null;
        try {
            FileInputStream fis = new FileInputStream(PATH);
            ois = new ObjectInputStream(fis);

            Object o = ois.readObject();
            Object o1 = ois.readObject();

            System.out.println(o + "\n" + o1);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

transient: 标注的属性不会被序列化。不会存储到文件中

public class Demo09 {
	public static void main(String[] args)throws Exception {
		Bird bird = new Bird("孔雀", 20);
		FileOutputStream fos = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\bird.ser");
		ObjectOutputStream oos = new ObjectOutputStream(fos);

		oos.writeObject(bird);

		oos.close();

		System.out.println("------------------------");

		FileInputStream fis = new FileInputStream("C:\\Users\\GzhAnkh\\Desktop\\bird.ser");
		ObjectInputStream ois = new ObjectInputStream(fis);

		Object object = ois.readObject();
		System.out.println(object);
	}
}
/*
* transient修饰符,瞬派
* */
class Bird implements Serializable {
	private String kind;
	private transient int age;

	@Override
	public String toString() {
		return "Bird{" +
			"kind='" + kind + '\'' +
			", age=" + age +
			'}';
	}

	public Bird(String kind, int age) {
		this.kind = kind;
		this.age = age;
	}
}

小练习:使用对象流保存一个含有100个学生的集合。

/*
*	分析:	1、准备一个集合
*	        2、往集合中添加100个学生对象 *
*               3、创建对象输出流
*		4、输出List对象
*		5、关闭流, 释放资源。
* */
public class Demo10 {
    public static void main(String[] args) {
        ArrayList<Student> students = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            students = new ArrayList<>();
            for (int i = 0; i < 100; i++) {
                Student student = new Student(2018000 + i, "name" + i, i + 10, "j1o9");
                students.add(student);
            }
            System.out.println(students.size());

            FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\GzhAnkh\\Desktop\\Students.ser");
            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(students);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                objectOutputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

标签:String,对象,age,new,ois,public
来源: https://www.cnblogs.com/Gzh001007/p/15054570.html