博客
关于我
java之 属性集 & 缓冲流 & 序列化流
阅读量:393 次
发布时间:2019-03-05

本文共 7451 字,大约阅读时间需要 24 分钟。

0x01、属性集

1、Properties类的概述

java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。加载文件中配置信息等等

2、Properties类的构造方法

public Properties()` :创建一个空的属性列表。

3、Properties类存储方法

public Object setProperty(String key, String value) : 保存一对属性。  public String getProperty(String key)  :使用此属性列表中指定的键搜索属性值。public Set
stringPropertyNames() :所有键的名称的集合。

示例代码:

public static void main(String[] args) throws FileNotFoundException {        // 创建属性集对象        Properties properties = new Properties();        // 添加键值对元素        properties.setProperty("filename", "a.txt");        properties.setProperty("length", "209385038");        properties.setProperty("location", "D:\\a.txt");        // 打印属性集对象        System.out.println(properties);        // 通过键,获取属性值        System.out.println(properties.getProperty("filename"));        System.out.println(properties.getProperty("length"));        System.out.println(properties.getProperty("location"));        // 遍历属性集,获取所有键的集合        Set
strings = properties.stringPropertyNames(); // 打印键值对 for (String key : strings ) { System.out.println(key+" -- "+properties.getProperty(key)); } }

输出结果:

{filename=a.txt, length=209385038, location=D:\a.txt}a.txt209385038D:\a.txtfilename -- a.txtlength -- 209385038location -- D:\a.txt

4、Properties类与流相关的方法

public void load(InputStream inStream): 从字节输入流中读取键值对。public void load(Reader reader): 从字节输入流中读取键值对。

参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。

加载代码演示:

public class Test3 {    public static void main(String[] args) throws Exception{        /*		 注意:          1.文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。          2.如果配置文件中有中文,那么加载文件文件时,使用字符流,但是开发中一般配置文件中不要写中文         */                // 创建Properties对象        Properties pro = new Properties();        // 往pro对象中添加键值对        pro.setProperty("username", "root");        pro.setProperty("password", "123456");        pro.setProperty("url", "http://www.baidu.com");        // 把pro对象中的键值对写入到文件中        FileOutputStream fos = new FileOutputStream("db2.properties");        pro.store(fos,"itheima");        // 关闭流        fos.close();    }

加载(读取)配置文件中的数据

private static void method01() throws IOException {        // 1.加载(读取)配置文件中的数据        // 创建Properties对象        Properties pro = new Properties();        // 调用load方法加载配置文件中的数据        //FileInputStream fis = new FileInputStream("a.txt");        FileInputStream fis = new FileInputStream("db2.properties");        pro.load(fis);// 把关联文件中的数据以键值对的形式存储到pro对象中        // 关闭流,释放资源        fis.close();        // 打印pro对象        System.out.println(pro);        System.out.println("--------------------------------------------------");        // 注意事项: 如果配置文件中有中文 使用字符流        // 创建Properties对象        Properties pro2 = new Properties();        // 调用load方法加载配置文件中的数据        FileReader fr = new FileReader("a.txt");        pro2.load(fr);// 把关联文件中的数据以键值对的形式存储到pro对象中        // 关闭流,释放资源        fr.close();        // 打印pro对象        System.out.println(pro2);    }}

0x02、缓冲流

缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流BufferedInputStreamBufferedOutputStream
  • 字符缓冲流BufferedReaderBufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

1、字节缓冲流

public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。 public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字节缓冲输入流BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));// 创建字节缓冲输出流BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));

使用缓冲流读写一个字节拷贝文件

public class BufferedDemo {    public static void main(String[] args) throws Exception {       long start = System.currentTimeMillis();        // 创建字节输入流对象,关联数据源文件路径        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("B_test.exe"));        // 创建字节输出流对象,关联目的地文件路径        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E_test.exe"));        // 定义一个int类型的变量,用来存储读取到的字节数据        int len;        // 循环读取        while ((len = bis.read()) != -1) {            // 在循环中,写出数据            bos.write(len);        }        // 关闭流,释放资源        bos.close();        bis.close();        long end = System.currentTimeMillis();        System.out.println("总共需要:" + (end - start) + "毫秒");// 大约32秒    }}

使用缓冲流读写一个数组字节拷贝文件

public class BufferedDemo {    public static void main(String[] args) throws FileNotFoundException {        long start = System.currentTimeMillis();        // 创建字节输入流对象,关联数据源文件路径        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("B_test.exe"));        // 创建字节输出流对象,关联目的地文件路径        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E_test.exe"));        // 定义一个字节数组,用来存储读取到的字节数据        byte[] bys = new byte[8192];        // 定义一个int类型的变量,用来存储读取到的字节数据        int len;        // 循环读取        while ((len = bis.read(bys)) != -1) {            // 在循环中,写出数据            bos.write(bys,0,len);        }        // 关闭流,释放资源        bos.close();        bis.close();        long end = System.currentTimeMillis();        System.out.println("总共需要:" + (end - start) + "毫秒");// 大约4秒    }}

0x03、序列化流

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据对象的类型对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化对象的数据对象的类型对象中存储的数据信息,都可以用来在内存中创建对象。看图理解序列化:

1、ObjectOutputStream类

(1)构造方法:

public ObjectOutputStream(OutputStream out): 创建一个指定OutputStream的ObjectOutputStream。

代码示例:

FileOutputStream fileOut = new FileOutputStream("employee.txt");ObjectOutputStream out = new ObjectOutputStream(fileOut);

一个对象要想序列化,必须满足两个条件:

  • 该类必须实现java.io.Serializable 接口,Serializable 是一个标记接口
public final void writeObject (Object obj) : 将指定的对象写出。

示例代码:

public class Test {    public static void main(String[] args)throws Exception {        // 创建Student对象        Student s = new Student("张三", 18);        // 需求:将s对象写入到 C:\\Users\\86183\\Desktop\\ser.txt 文件中                // 创建序列化流对象,关联目的地文件路径        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\86183\\Desktop\\ser.txt"));        // 写出对象        oos.writeObject(s);        // 关闭流,释放资源        oos.close();    }}

 对象序列化包括如下步骤:

1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;2) 通过对象输出流的writeObject()方法写对象。

2、ObjectInputStream类

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

(1)构造方法

public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

public final Object readObject () : 读取一个对象。

示例代码:

public class Test {    public static void main(String[] args) throws Exception{        // 反序列化:读取之前序列化的对象        // 1.创建反序列化流对象,关联数据源文件路径        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\Users\86183\Desktop\ser.txt"));        // 2.读取一个对象        Object obj = ois.readObject();        System.out.println(obj);        // 3.关闭流,释放资源        ois.close();    }}

对象反序列化的步骤如下:

1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;2) 通过对象输入流的readObject()方法读取对象。

3、小结

  我们可以看到,先通过输入流创建一个文件,再调用ObjectOutputStream类的 writeObject方法`,把序列化的数据写入该文件;

​ 然后调用ObjectInputStream类的readObject方法反序列化数据并打印数据内容

反序列化的注意事项

  • 对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个 ClassNotFoundException 异常。

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

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

Serializable 接口给需要序列化的类,提供了一个序列版本号。serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

转载地址:http://dxxzz.baihongyu.com/

你可能感兴趣的文章
脱壳与加壳-加壳-6-代码实现加密导入表
查看>>
Typora配置PicGo时,提示Failed to fetch
查看>>
ASP.NET CORE MVC 实现减号分隔(Kebab case)样式的 URL
查看>>
bcolz的新操作
查看>>
Linux的s、t、i、a权限(转)
查看>>
zmq的send
查看>>
C++中的delete加深认识
查看>>
windows消息机制(转)
查看>>
STL笔试面试题总结(干货)(转)
查看>>
XML 和 HTML 之间的差异
查看>>
阿里钉钉面试题
查看>>
华为社招笔试
查看>>
C++中找资源或者函数的方法
查看>>
一些留给自己的思考题(只求回过头来能够有所获)
查看>>
SQL函数返回表的写法
查看>>
delete对象时会自动调用类的析构函数
查看>>
C++ 子类对象直接赋值给父类对象可行,反过来不行
查看>>
linux下同一个动态库名为何辣么多的.so文件
查看>>
SQL联表的方式(逗号, Left Join, Right Join)
查看>>
牛客网输入输出举例
查看>>