IO流-对象流

    技术2022-07-10  149

    文章目录

    概述序列化概述`ObjectOutputStream`构造器常用方法 反序列化概述`ObjectInputStream`构造器常用方法 对象可序列化概述`Serializable`对象可序列化的注意: 对象流使用示例

    概述

     对象流是处理流的一种,用于将内存中的对象写入到数据源,并且能够将对象从数据源还原到内存。

    序列化

    概述

     将对象写入到数据源的过程称为对象的序列化。对象的序列化过程中,对象转化为与平台无关的二进制序列,通过对象流将二进制序列写入本地磁盘,或者将二进制序列传输到另一网络节点。 实现对象序列化的流:ObjectOutputStream.

    ObjectOutputStream

     ObjectOutputStream是处理流的一种。ObjectOutputStream类继承OutputStream抽象类,并且实现ObjectOutput接口和DataOutput接口。

    构造器

    public ObjectOutputStream(OutputStream out) throws IOException {}

    常用方法

    /* 刷新流 */ public void flush() throws IOException {} public void write(int val) throws IOException {} public void write(byte[] buf) throws IOException {} public void write(byte[] buf,int off,int len) throws IOException {} public void writeBoolean(boolean val) throws IOException {} public void writeInt(int val) throws IOException {} public void writeFloat(float val) throws IOException {} public void writeDouble(double val) throws IOException {} public void writeChar(int val) throws IOException {} public void writeByte(int val) throws IOException {} public void writeLong(long val) throws IOException {} public void writeShort(short val) throws IOException {} public void writeChars(String str) throws IOException {} public void writeBytes(String str) throws IOException {} public void writeUTF(String str) throws IOException {} public void close() throws IOException {} /* 写入指定对象到流 */ public final void writeObject(Object obj) throws IOException {}

    反序列化

    概述

     将对象从数据源还原到内存的过程成为反序列化。实现对象反序列化的流:ObjectInputStream.

    ObjectInputStream

     ObjectInputStream是处理流的一种。ObjectInputStream类继承InputStream抽象类,并且实现ObjectInput接口和DataInput接口。

    构造器

    public ObjectInputStream(InputStream in) throws IOException {}

    常用方法

    public void available() throws IOException {} public int read() throws IOException {} public int read(byte[] buf,int off,int len) throws IOException {} public boolean readBoolean() throws IOException {} public int readInt() throws IOException {} public float readFloat() throws IOException {} public double readDouble() throws IOException {} public char readChar() throws IOException {} public byte readByte() throws IOException {} public long readLong() throws IOException {} public short readShort() throws IOException {} public String readUTF() throws IOException {} public void close throws IOException {} /* 从流读出一个对象 */ /* 注意: 1.如果数据源中存在多种类型的对象序列,使用readObject()读取对象时注意类型匹配。 一般要求实例引用按照writeObject()写入的顺序接收readObject()的返回。 2.在数据源的末尾(没有更多对象序列时)使用readObject()会抛java.io.EOFException. */ public final Object readObject() throws IOException, ClassNotFoundException {}

    对象可序列化

    概述

     不是所有类型的对象都能被序列化,只有可序列化的对象才能被序列化。使用对象流序列化不可序列化的对象时,将抛NotSerializableException.可使用Serializable接口使对象可序列化。

    Serializable

     Serializable是java.io包下的标记接口(空接口),实现Serializable接口可使对象可序列化。 类实现Serializable接口时只需要显示指定Serializable接口中的静态常量:

    static final long serialVersionUID = 42L;

     serialVersionUID用于标记类的序列化版本。未显式指明时,系统将根据内部细节自动分配值。对于类的不同实例变量,serialVersionUID值可能分配不同。如果使用不同的实例变量接收反序列化的结果,系统会认为序列化版本不一致,抛InvalidCastException.  因此,必须显式指定SerialVersionUID的值(任意即可)。

    public class Person implements Serializable { /* 任意指定,无具体限制 */ /* 没有引用价值的常量,推荐使用 private 修饰 */ private static final long serialVersionUID = 5201314L; }

    对象可序列化的注意:

     ①使对象可序列化时,要求对象的所有属性均为可序列化的。Java中的基本数据类型和String都是可序列化的。

     ②使对象可序列化时,对象类中的静态成员不被序列化,因为静态成员归属于类,而并非归属于对象。

     ③对象中transient关键字修饰的成员不被序列化。如果要求对象中的某些成员不被序列化,可使用transient关键字修饰目标成员。

    对象流使用示例

    Account.java

    public class Account implements Serializable { //任意指定serialVersionUID的值 private static final long serialVersionUID = 1003L; private String name; private long number; private String password; private static final String sp = File.separator; //账户存储文件 private static final File savePath = new File("F:"+sp+"Desktop"+sp+"account.txt"); public Account(String name,long number,String password) { this.name = name; this.number = number; this.password = password; } public void setName(String name) {this.name = name;} public String getName() {return name;} public void setNumber(long number) {this.number = number;} public long getNumber() {return number;} public void setPassword(String password) {this.password = password;} public String getPassword() {return password;} public void save() { ObjectOutputStream oos = null; try{ //覆盖原数据 oos = new ObjectOutputStream(new FileOutputStream(savePath,false)); oos.writeObject(this); oos.flush(); } catch(IOException e){ e.printStackTrace(); } finally{ if(oos != null){ try{ oos.close(); } catch(IOException e){ e.printStackTrace(); } } } } //一台设备只有一个账户,使用静态方法获取 public static Account getAccount() { ObjectInputStream ois = null; Account a = null; try{ ois = new ObjectInputStream(new FileInputStream(savePath)); a = (Account) ois.readObject(); } catch(Exception e){ e.printStackTrace(); } finally{ if(ois != null){ try{ ois.close(); } catch(IOException e){ e.printStackTrace(); } } } return a; } @Override public String toString(){ String str = "--------------------\n" + "name : " + name + "\n--------------------\n" + "number : " + number + "\n--------------------\n" + "password : " + password + "\n--------------------\n"; return str; } }

    Main.java

    public class Main { public static void main(String[] args) { Account account = new Account("Tony",18372602180L,"123456789"); account.save(); System.out.println(Account.getAccount()); //更改密码 account.setPassword("abc.123"); account.save(); System.out.println(Account.getAccount()); } }

    运行结果:

    -------------------- name : Tony -------------------- number : 18372602180 -------------------- password : 123456789 -------------------- -------------------- name : Tony -------------------- number : 18372602180 -------------------- password : abc.123 --------------------
    Processed: 0.012, SQL: 9