2019-03-07

作者: DreamPath | 来源:发表于2019-03-07 23:49 被阅读15次

序列化流,打印流基础知识整理

序列化流(对象流)

把对象以流的形式存储在硬盘上或者数据库中的过程就是写序列化流。
原理:

  • 1.Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据 、对象的类型和 对象中存储的属性等信息。
  • 2.字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
  • 3.反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。 对象的数据 、 对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。
    图片.png
    对象输出流:
    java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。
package obj_outputStream;

/**
 * public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream
 * 该类必须实现 java.io.Serializable 接口, Serializable 是一个标记接口,不实现此接口的类将不会使任 何状态序列化或反序列化,会抛出 NotSerializableException 。 
 * 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,
 * 则该属性必须注明是瞬态的,使用 transient 关键字修饰。
 */
public class Employee implements java.io.Serializable{
    public String name;
    public String address;
    public transient int age;// transient瞬态修饰成员,不会被序列化

    public void checkAddress(){
        System.out.println("Address check:"+name+"---"+address);
    }

}

2.写出对象方法

package obj_outputStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 * public final void writeObject (Object obj) : 将指定的对象写出
 */
public class Serializable_obj {
    public static void main(String[] args) {

        Employee e = new Employee();
        e.name="周星驰";
        e.address="香港";
        e.age=65;

        try {
            FileOutputStream fileOut=new FileOutputStream("D:\\Java代码\\Java基础加强\\sjs.txt");
            ObjectOutputStream obj=new ObjectOutputStream(fileOut);

            obj.writeObject(e);
                obj.close();
                fileOut.close();
            System.out.println("Serialized data is save!");// 姓名,地址被序列化,年龄没有被序列化。
        } catch (IOException e1) {
            e1.printStackTrace();
        }//Serialized data is save!


    }

}

对象输入流:
ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

package obj_outputStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 *   public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream
 *  如果能找到一个对象的class文件,我们可以进行反序列化操作,调用
 *  ObjectInputStream 读取对象的方法:
 *  public final Object readObject () : 读取一个对象
 *  
 *  注意:
 *  对于JVM可以反序列化对象,它必须是能够找到class文件的类。
 *  如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。 
 */
public class InputStreamDemo {
    public static void main(String[] args) {
        Employee e=null;

        try {
            FileInputStream in=new FileInputStream("D:\\Java代码\\Java基础加强\\sjs.txt");
            ObjectInputStream inputStream=new ObjectInputStream(in);

           e=(Employee)inputStream.readObject();

                inputStream.close();
                in.close();

        } catch (IOException | ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        System.out.println("Name:"+e.name);
        System.out.println("Address:"+e.address);
        System.out.println("Age:"+e.age);
        /**输出结果:
         * Name:周星驰
         * Address:香港
         * Age:0     (年龄未被序列化存储,默认为0)
         */
    }
}
反序列化操作2

当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配
  • 该类包含未知数据类型
  • 该类没有可访问的无参数构造方法
package obj_outputStream;

/** 
 * public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream
 */
public class Employee implements java.io.Serializable{
  
    // 序列化2
    private static final long serialVersionUID=1l;
    public String name;
    public String address;
    public int eit;
    public void checkAddress(){
        System.out.println("Address check:"+name+"---"+address);
    }
}
序列化集合

1.将存有多个自定义对象的集合序列化操作,保存到 list.txt 文件中。

  1. 反序列化 list.txt ,并遍历集合,打印对象信息。

创建学生类

package obj_outputStream;

import java.io.Serializable;

/**
 * 1. 把若干学生对象 ,保存到集合中。
 * 2. 把集合序列化。
 * 3. 反序列化读取时,只需要读取一次,转换为集合类型。
 * 4. 遍历集合,可以打印所有的学生信息
 */
public class Student implements Serializable {
    private String name;
    private int age;

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

    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;
    }
}

测试类

package obj_outputStream;

import java.io.*;
import java.util.ArrayList;

public class ArrayObject {
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Student student = new Student("李小龙", 22);
        Student student1 = new Student("王五", 42);
        Student student2 = new Student("叶问", 52);
        Student student3 = new Student("霍元甲", 32);

        ArrayList<Student> students = new ArrayList<>();
        students.add(student);
        students.add(student1);
        students.add(student2);
        students.add(student3);
        // 序列化操作
        serializ(students);
        //反序列化操作
        ObjectInputStream stream = new ObjectInputStream(new FileInputStream("aaa.txt"));
        // 读取对象,强转为ArrayList类型
        ArrayList<Student> list = (ArrayList<Student>) stream.readObject();
        for (int i = 0; i < list.size(); i++) {
            Student s = list.get(i);

            System.out.println("姓名:" + s.getName() + "----" + "年龄" + s.getAge());
        }
        stream.close();

    }
        //传递存储对象的集合
    private static void serializ(ArrayList<Student> students) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("aaa.txt"));
        out.writeObject(students);
        out.close();


    }
}

打印流

只做输出没有输入
分为字节打印流和字符打印流
PrintWriter:字符打印流
特点:

  • 1.可以打印各种数据类型。
  • 2.封装了字符输入流,还可以实现字符流和字节流的转换。
  • 3.可以使用自动刷新,则只有再调用println,printf或者format的其中一个方法时才能完成此操作。
  • 4.可以直接向文件中写数据。
package obj_outputStream;

import java.io.IOException;
import java.io.PrintStream;

/**
 * public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流
 * PrintStream ps = new PrintStream("ps.txt")
 */
public class printStreamDemo {
     public static void main(String[] args) throws IOException {
         // 调用系统的打印流,控制台直接输出97                  
          System.out.println(97);
          // 创建打印流,指定文件的名称                  
         PrintStream ps = new PrintStream("ps.txt");
         // 设置系统的打印流流向,输出到ps.txt            
          System.setOut(ps);
          // 调用系统的打印流,ps.txt中输出97           
         System.out.println(97); }
    }
}

相关文章

网友评论

    本文标题:2019-03-07

    本文链接:https://www.haomeiwen.com/subject/bkdhpqtx.html