对象具有状态和行为两种属性。行为存在类中的方法中,想要保存状态有多种方法,这里介绍两种:
一是保存整个当前对象本身(通过序列化);一是将对象中各个状态值保存到文件中(这种方式可以给其他非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() );
}
 
 
 
 
 
 
 
 

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

  1. java基础三 [深入多态,接口和多态](阅读Head First Java记录)

    抽象类和抽象方法 1.抽象类的声明方法,在前面加上抽象类的关键词abstract abstract class canine extends animal{      public void roam ...

  2. Java基础八--构造函数

    Java基础八--构造函数 一.子父类中构造函数的特点 1.1 为什么在子类构造对象时,发现,访问子类构造函数时,父类也运行了呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句. super( ...

  3. qemu:///system 没有连接驱动器可用;读取数据时进入文件终点: 输入/输出错误

    原因 1. KVM的相关包 装少了 2KVM的相关包 重新安装 3 May 31 15:22:55 localhost libvirtd: 2019-05-31 07:22:55.554+0000: ...

  4. Java基础--对象的序列化

    所有分布式应用常常需要跨平台,跨网络,因此要求所有传的参数.返回值都必须实现序列化. 比如常见的Dubbo分布式平台,里面的对象实体类必须实现序列化才能在网络间传递 一.定义 序列化:把Java对象转 ...

  5. java基础十一[远程部署的RMI](阅读Head First Java记录)

    方法的调用都是发生在相同堆上的两个对象之间(同一台机器的Java虚拟机),如果想要调用另一台机器上的对象,可以通过Socket进行输入/输出. 远程过程调用需要创建出4种东西:服务器.客户端.服务器辅 ...

  6. Java基础知识:序列化和反序列化

    一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...

  7. Java基础(八)--String(源码)、StringBuffer、StringBuilder

    String源码:基于jdk1.8 public final class String implements Serializable, Comparable<String>, CharS ...

  8. Java基础(八)

    IO流 概述与分类 Java中的IO流技术主要用于传输数据.典型的应用场景有:读写本地文件,上传下载文件等.按照数据传输的方向可以分为两种: l  输入流(Input):既让数据进入应用程序中. l  ...

  9. Java基础之使用Scanner类获取用户输入

    创建 Scanner 对象的基本语法: Scanner s = new Scanner(System.in); Scanner 类的 next() 方法 import java.util.Scanne ...

随机推荐

  1. 第七课 第二节,T语言流程语句(版本5.0)

    while语句 循环结构是程序中一种很重要的结构其特点是,在给定条件成立时,反复执行某程序段,直到条件不成立为止给定的条件称为循环条件,反复执行的程序段称为循环体 (注:关键字,while,end) ...

  2. 评价photoshop

    Adobe Photoshop,简称“PS”,是一个由Adobe开发和发行的图像处理软件. 2003年,Adobe的Creative Suite套装将Adobe Photoshop 8更名为Adobe ...

  3. 1、C#入门第一课

    C# 读作C Sharp,所以程序文件的扩展名为.cs 新建项目-窗体应用程序 所谓的Visual C#就是指的可视化编程,主要在设计窗口布置好自己的控件(一些具有一定功能的小部件,例如如可以点击的按 ...

  4. Android学习四:数据库操作

    1前言 android中使用SQLite作为数据库,在进行相关的开发的时候不需要导入包.SQLite起符合SQL标准,也有自己的一些特性,是一个轻量级的数据库. 2代码 简单的数据库类封装 packa ...

  5. asp 实现域名转向

    <% host=lcase(request.servervariables("HTTP_HOST")) select CASE host CASE "aa.cn&q ...

  6. linux网络环境下socket套接字编程(UDP文件传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  7. FFmpeg.exe使用随笔

    一.将图片合成为MP4 1.将照片合成为h264 ffmpeg -framerate 12 -i %3d.png -c:v libx264 -pix_fmt yuv420p test.h2642.将h ...

  8. 12 Linux下crontab详解

    1. 概述: crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进 ...

  9. 分布式任务分发框架Gearman教程和PHP实现实例

    1.Gearman介绍和使用场景 Gearman是一个分发任务的程序框架,可以用在各种场合,与Hadoop相 比,Gearman更偏向于任务分发功能.它的任务分布非常简单,简单得可以只需要用脚本即可完 ...

  10. Android学习笔记(四)

    一个应用程序是有很多活动构成的,使用Intent在活动间移动. Intent分为显式和隐式两种: 1.显示Intent: 新建一个布局文件,命名为second_layout.xml,代码如下 < ...