• java基础八 [序列化和文件的输入/输出](阅读Head First Java记录)


    对象具有状态和行为两种属性。行为存在类中的方法中,想要保存状态有多种方法,这里介绍两种:
    一是保存整个当前对象本身(通过序列化);一是将对象中各个状态值保存到文件中(这种方式可以给其他非JAVA程序用),如果其他程序需要用到的状态,可以通过特定的格式存储到文本中,方便其他程序解析提取数据
     
    序列化(serialization)
    只有自己写的JAVA程序用到存储的数据时,使用序列化
    序列化将整个对象写入到文件中,该对象引用的实例变量、所有被引用的对象都会被序列化
     
    创建一个可以被序列化的类
    只有实现了Serializable接口的类可以被序列化(实际上Serializable没有任何方法需要实现,它的目的只是声明这个类是可以被序列化的)
    实现了Serializable接口的类,它的子类也是都可以被序列化的
    需要import java.io.Serializable
    例如:
    import java.io.Serializable;
    public class Box implements Serializable{
        private int width;
        private int height;
        transient int size;\transient关键字,标识该实例变量不会被序列化
        private Duck duck =new Duck();
        public void setWidth(int w){
            width=w;
        }
        public void setHeight(int h){
            height=h;
        }
    }
    实例变量width和height、duck的值,在序列化时值会被保存
    实例变量size不会被序列化,因为用transient关键字的实例变量不进行序列化,会以null等默认值返回(有可能有些引用变量作者没有进行序列化,或者某些字段没有序列化的意义)
     
    序列化是全有或全无的,一部分序列化失败了就不会保存:如果实例变量的引用对象duck,如果类Duck没有实现序列化的话,当前类也不能被序列化,否则会报错
     
    序列化的步骤
    第一步:创建FileOutputStream,FileOutputStream把字节写入文件
    FileOutputStream fs = new FileOutputStream("foo.ser);\如果文件footsore不存在,会自动创建该文件
     
    第二步:创建ObjectOutputStream,ObjectOutputStream把对象转换成可以写入串流的数据
    ObjectOutputStream os = new ObjectOutputStream(fs);\fs是一个FileOutputStream对象
     
    第三步:写入对象,ObjectOutputStream调用writeObject方法把对象打成串流送到FileOutputStream来写入文件
    os.writeObject(myBox);\myBox必须是一个实现了Serializable接口的类,是可以序列化的
     
    第四步:关闭ObjectOutputStream
    os.close();\关闭所关联的输出串流
     
    反序列化【解序列化】(Deserialization):还原对象
    序列化的反向操作,将对象恢复到存储时的状态,transient的变量不会恢复当时的状态,只会恢复成默认值,例如null。如果是不可序列化的类,会重新执行构造函数。序列化的类不会执行构造函数,会将新对象放到对上。
    对象是从stream中读出来的,Java虚拟机通过存储信息判断要恢复的对象class的类型,如果找不到或无法加载该类,会抛出异常。
     
    解序列化的步骤:
    第一步:创建FileInputStream,读取文件字节,如果文件不存在会抛出异常
    FileInputStream fileStream = new FileInputStream("foo.ser);\如果文件不存在,会抛出异常
     
    第二步:创建ObjectInputStream,将自己转换成对象的stream
    ObjectInputStream os=new ObjectInputStream(fileStream);
     
    第三步:读取对象,会按照os.writeObject(xx)存储的顺序读取,与写入顺序相同
    Object one=os.readObject();
    Object two=os.readObject();
     
    第四步:转换对象类型。默认返回的是Object类型,需要强转换为存储时的类型
    GamecCharacter test1=(GameCharacter) one;
    GamecCharacter test2=(GameCharacter) two;
     
    第五步:关闭ObjectInputStream
    os.close();
     
    serialVersionUID
    用来解序列化还原时比对,是否和当前Java虚拟机上的类的UID一致,如果版本不符就会在还原过程中抛出异常。
    查询类的serialVersionUID:在Java Development Kit中使用命令【serialver 类名】查询
     
    具体步骤如下,例如java文件为Box.java,进入java文件目录,通过javac xxx.java把文件编译为.class文件,然后通过serialver xxx查询
     
    如果完全想自己控制,可以将serialVersionUID写在class类中,但是这种就需要自己去承担类变动后,还原的对象一些实例变量可能不符的后果
    使用方法如下:
    public class Dog{
         static final long serialVersionUID=xxxxxx;
         //其他代码
    }
    这种情况如果后续类新增了字段或实例,反序列化时会将新增的字段初始为默认值
     
    序列化总结的一些点
    可以通过序列化来保存对象的状态
    Stream是连接串流(表示源和目的地)或链接用的串流(衔接连接串流,例如从FileOutputStream到ObjectOutputStream)
    只有实现了序列化接口的类才可以被序列化,所有实例都会被序列化(除非用来transient关键词会跳过)
    静态变量不会被序列化,每个类共享一个静态变量
     
    文件的输入输出
    有时候需要把对象的状态存储为单纯文件,来提供给其他非JAVA得应用程序,所以这里讲了文件的输入和输出
    java.io.File class
    File这个类代表磁盘上的文件,但是不是文件的内容。可以把它想象成文件路径
     
    File的简单应用
    1.创建代表现存盘文件的File对象
    File f = new File(“xxxx/mycode.txt”)
     
    2.建立新的目录
    File dir = new File(“chapter")
     
    缓冲区
    可以理解为购物车,为了省去磁盘操作的时间,,可以提高IO读写的效率
    BufferedReader和BufferedWrite各被分配了8192个字的缓冲区
     
    BufferedWrite:使用缓冲区来进行写操作,文件不会直接写入磁盘,而是先写入到缓冲区,当缓冲区满了时一次性写入到磁盘,减少直接操作磁盘的次数,提高效率。或者通过write.flush()来强制缓存区立即写入
    用法:
    只通过FileWrite写入的方法:
    File fs=new File(“filename”);
    FileWriter fw=new FileWriter(fs);
    fs.write(“xxx”);
     
    通过缓冲区进行写入的方法:
    File fs=new File(“filename”);
    FileWriter fw=new FileWriter(fs);
    BufferedWrite bw=new BufferedWrite(fw);
    bw.write(“xxx”);
     
    BufferedReader:将FileReader链接到BufferedReader也会提升效率,BufferedReader会将文件读入的字节置入缓冲区。当以后使用read()等操作进行读时,会先从缓存中读取,当缓存中为空时再从文件中直接读取
    用法:
    File fs=new File(“filename”);
    FileReader fr=new FileReader(fs);
    BufferedReader br=new BufferedReader(fr);
    while(br.readeLine() != null){//下面就是读取每一行的文件并打印了
         System.out.println(br.readeLine() );
    }
     
     
     
     
     
     
     
     
  • 相关阅读:
    pycharm的list的应用
    pycharm的list中copy的应用
    pycharm的list中clear的应用
    pycharm的list中append的应用
    crontab 管理指定用户的定时任务
    vsftp 搭建及虚拟账号配置
    MySQL 主从配置
    Ant 学习及常用任务
    ansible 小试
    微信H5页面分享
  • 原文地址:https://www.cnblogs.com/meitian/p/5803770.html
Copyright © 2020-2023  润新知