第3节 IO(下)

一、.properties文件与Properties类

1.1 .properties文件介绍

.properties文件一种属性文件,以键值对 的格式存储内容,在Java中可以使用Properties类来读取这个文件,一般来说它作为一些参数的存储,作为配置文件使用。

1.2 Properties类

它是Hashtable的子类,使用键值对来存储数据。

构造方法:

方法:

1、根据键获取值:

2、将键值对打印到指定的输出流:

3、从输入字节流或字符流中读取全部内容:

4、返回所有键的枚举:

5、新增键值对:

6、存储到字节输出流或字符输出流,comment是备注,写在存储文件的开头:

7、返回所有的值,以Set类型:

看个例子:

package com.kaikeba.coreclasslibrary.io;import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.Properties;public class properties {public static void main(String[] args) throws IOException {//.properties文件与Properties类//新建一个Properties对象Properties ppt = new Properties();//新建键值对ppt.setProperty("name","三体");ppt.setProperty("info","科幻小说");//要写入的字符流FileWriter fw = new FileWriter("book.properties");//往fw中存储该键值对集合的对象,备注为"存储的图书"ppt.store(fw, "存储的图书");fw.close();//从.properties文件读取属性Properties ppt2 = new Properties();Reader r = new FileReader("book.properties");ppt2.load(r);System.out.println(ppt.get("name"));System.out.println(ppt.get("info"));}
}输出为:
三体
科幻小说

且book.properties文件中存储的内容为:

最上面是备注信息,使用了Unicode编码。

二、序列化与反序列化

Java序列化是指把java对象转换为字节序列的过程 ,Java反序列化是指把字节序列恢复为java对象的过程通过序列化和反序列化实现网络传输、本地存储的目的

2.1 Serializable实现Java序列化

要实现java对象的序列化,只要将类实现标识接口 ——Serializable接口即可,不需要我们重写任何方法就可以实现序列化。

编写书籍类:

package com.kaikeba.coreclasslibrary.io.serializable;import java.io.Serializable;public class Book implements Serializable {private String name;private String info;private Person user;@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", info='" + info + '\'' +", user=" + user +'}';}public Book() {}public Book(String name, String info, Person user) {this.name = name;this.info = info;this.user = user;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}public Person getUser() {return user;}public void setUser(Person user) {this.user = user;}
}

编写借书人类:注意Book中有Person类的对象属性,所以Person类也要实现Serializable接口

package com.kaikeba.coreclasslibrary.io.serializable;import java.io.Serializable;public class Person implements Serializable {private String name;private int age;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public Person() {}public Person(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 com.kaikeba.coreclasslibrary.io.serializable;import java.io.*;public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化Person p = new Person("smile", 23);Book b = new Book("三体", "科幻小说", p);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));oos.writeObject(b);oos.close();//反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));Book book = (Book) ois.readObject();System.out.println(book);}
}

结果如下:

原始对象:
Book{name='三体', info='科幻小说', user=Person{name='smile', age=23}}
反序列化之后的对象:
Book{name='三体', info='科幻小说', user=Person{name='smile', age=23}}

主要是使用到了ObjectOutputStreamObjectInputStream类,ObjectOutputStream类使用writeObject将对象写到文件中,ObjectInputStream类使用readObject将对象从文件中读取出来。

2.2 部分属性的序列化

实现部分字段序列化的方式:

  • 使用transient修饰符

  • 使用static修饰符

  • 默认方法writeObject和readObject

  • Externalizable实现

2.2.1 使用transient修饰符

修改实体类,将实体类中不想被序列化的属性添加transient修饰符。

public class Book implements Serializable {private String name;private transient String info;private Person user;... public class Person implements Serializable {private String name;private transient int age; ...

结果如下:

原始对象:
Book{name='三体', info='科幻小说', user=Person{name='smile', age=23}}
反序列化之后的对象:
Book{name='三体', info='null', user=Person{name='smile', age=0}}

transient修饰的属性都没有被序列化,因此反序列化的结果也是默认值。

2.2.2 使用static修饰符

static修饰符修饰的属性会参与序列化,但是如果在反序列化的时候对其进行重新赋值,反序列化后的结果会随之改变:

public class Book implements Serializable {private String name;private static String info;private Person user;...public class Test {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化Person p = new Person("smile", 23);Book b = new Book("三体", "科幻小说", p);System.out.println("原始对象:\n"+b);ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("b.txt"));oos.writeObject(b);oos.close();//反序列化b.setInfo("中国最牛的科幻小说");ObjectInputStream ois = new ObjectInputStream(new FileInputStream("b.txt"));Book book = (Book) ois.readObject();System.out.println("反序列化之后的对象:\n"+book);}
}

结果:

原始对象:
Book{name='三体', info='科幻小说', user=Person{name='smile', age=23}}
反序列化之后的对象:
Book{name='三体', info='中国最牛的科幻小说', user=Person{name='smile', age=23}}

解释:其实就是静态属性被修改之后,因为所有对象都是用的同一个内容,所以反序列化的静态属性也就变了。

2.2.3 默认方法writeObject和readObject

   在Book中添加两个方法:
public class Book implements Serializable {private String name;private String info;private Person user;private void writeObject(ObjectOutputStream oos) throws IOException {System.out.println("writeObject---------------");oos.writeObject(name);oos.writeObject(user);}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {System.out.println("readObject----------------");name = (String) ois.readObject();user = (Person) ois.readObject();}...

结果为:

原始对象:
Book{name='三体', info='科幻小说', user=Person{name='smile', age=23}}
writeObject---------------
readObject----------------
反序列化之后的对象:
Book{name='三体', info='null', user=Person{name='smile', age=23}}

info属性没有写入两个函数中,就没有被序列化。

源码分析:

注意:添加的两个方法必须是private void修饰的,否则不生效。

首先看一下Serializable接口的描述:

ObjectStreamClass类:在序列化(反序列化)的时候,ObjectOutputStreamObjectInputStream)会寻找目标类中私有的writeObjectreadObject)方法,赋值给变量writeObjectMethodreadObjectMethod)。

通过上面这段代码可以知道,如果writeObjectMethod ≠ null(目标类中定义了私有的writeObject方法),那么将调用目标类中的writeObject方法,如果writeObject == null,那么将调用默认的defaultWriteMethod方法来读取目标类中的属性。

readObject的调用逻辑和WriteObject一样。

总结一下,如果目标类中没有定义私有的writeObjectreadObject方法,那么序列化和反序列化的时候讲调用默认的方法来根据目标类中的属性来进行序列化和反序列化,而如果目标类中定义了私有的writeObjectreadObject方法,那么序列化和反序列化的时候讲调用目标类指定的writeObjectreadObject方法来实现。

2.3 Externalizable实现java序列化

实现部分属性序列化的方式的第四种,通过Externalizable接口。

Externalizable继承自Serializable接口,使用Externalizable接口需要实现readExternal方法和writeExternal方法来实现序列化和反序列化。

Externalizable接口继承自Serializable接口,所以实现Externalizable接口也能实现序列化和反序列化。Externalizable接口中定义了writeExternalreadExternal两个抽象方法,这两个方法其实对应Serializable接口的writeObjectreadObject方法,可以这样理解:Externalizable接口被设计出来的目的就是为了抽象出writeObjectreadObject这两个方法,但是目前这个接口使用的并不多。

三、Serializable vs Externalizable

区别 Serializable Externalizable
实现复杂度 实现简单,java对其有内建支持 实现复杂,由开发人员自己完成
执行效率 所有对象由java统一保存,性能较低 开发人员决定哪个对象保存,可能造成速度提升
保存信息 保存时占用空间大 部分存储,可能造成空间减少
使用频率 偏低

JavaSE——IO(下)(Properties类、序列化与反序列化)相关推荐

  1. C# 实体类序列化与反序列化一 (XmlSerializer)

    /// <summary>/// 实体类序列化的反序列化的类/// </summary>/// <typeparam name="T">< ...

  2. json 反序列化 父子类型_Jaskson精讲第7篇-类继承关系下的JSON序列化与反序列化JsonTypeInfo...

    Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的, ...

  3. json 反序列化 父子类型_json类序列化与反序列化参考

    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Web;usingSystem.Runtime.Ser ...

  4. fileinputstream自定义类序列化和反序列化_Rest Assured篇:Java中的序列化和反序列化...

    点击上方蓝字设为星标 每天傍晚伴你一起成长! Java 中的序列化和反序列化是一个重要的编程概念.它适用于所有主要的编程语言.在本章中,我们将尝试在Java语言的上下文中理解此概念.在本章的最后,我们 ...

  5. spring boot添加 LocalDateTime 等 java8 时间类序列化和反序列化的支持

    由于项目将原有的  Date类型的字段改造为 LocalDate,LocalDateTime,LocalTime 类型, 发现  spring  对项目的时间格式无法自动转换,故需手动配置下. 在sp ...

  6. java IO(输入输出) 对象的序列化和反序列化

    //对象的序列化 package zhi_jie_liu;import java.io.FileInputStream; import java.io.FileNotFoundException; i ...

  7. C#中JSON序列化和反序列化

    有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境-- 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...

  8. Android开发中混淆后Gson序列化、反序列化的那些坑,androidstudio配置

    为什么呢? 因为反序列化创建对象本质还是利用反射, 会根据 json 字符串的 key 作为属性名称, value 则对应属性值. 如何解决 将序列化和反序列化的类排除混淆 使用 @Serialize ...

  9. Java序列化和反序列化(详解)

    一.理解Java序列化和反序列化 Serialization(序列化):将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程.序列化可以将数据永久保存在磁盘上(通常 ...

  10. avro 序列化java_Avro 对象序列化与反序列化,及转Json对象序列化处理

    Avro 工具类 序列化与反序列化 public class AvroHelper { public  byte[]serializeAvroToByteArray(List dcs) { try { ...

最新文章

  1. android studio数据库存储数据,如何使用API​​ 23在android studio中的数据库中存储数据?...
  2. 2020-11-27(switch的优化问题)
  3. jdk1.5-1.7新特性详细介绍
  4. python字典的键可以是int吗_Python:大int键的快速字典
  5. 一个mysql可以存多少数据类型_mysql一张表到底能存多少数据?
  6. postgresql9.6 的安装
  7. 消息队列与rabbitMQ的各种问题
  8. numpy中的数组复制
  9. C++:以空格分隔的字符串的输入输出
  10. 使用TF卡烧录Jetson NX开发板
  11. junit5教程_JUnit5教程
  12. 优锘科技:森模型插件上新:BIM秒变轻量化,模板任选效果
  13. 18款表白源码,搭建网站必备,总有一款适合你
  14. 微信小程序生成携带参数的小程序码
  15. Linux 虚拟内存管理思维导图
  16. 【大学物理·早期量子论和量子力学基础】量子力学中的氢原子问题
  17. 生物冰箱智能锁有哪些功能
  18. 多模态模型 CLIP4Clip 带你实现文本与视频互搜
  19. 记录一次生产CPU使用率100%问题排查
  20. 中国7大行业进入微利时代 房地产无法幸免未来5年中国最有钱景的9种工作

热门文章

  1. 忆阻器的matlab建模_忆阻器Simulink建模和图形用户界面设计.PDF
  2. termux配置python安装kali_安卓安装kali linux之Termux
  3. 不要再纠结卷积的公式啦!0公式深度解析全连接前馈网络与卷积神经网络!
  4. 论文浅尝 | 动态词嵌入
  5. NLP-美团技术团队(搜索-推荐-召回排序-Bert)
  6. 基于深度学习的FAQ问答系统
  7. 论文学习16-Going out on a limb: without Dependency Trees(联合实体关系抽取2017)
  8. 委托、Lambda表达式、事件系列07,使用EventHandler委托
  9. python replace()
  10. 洛谷 P1377 [TJOI2011]树的序 解题报告