张小飞的Java之路——第四十四章——其他流对象

写在前面:

视频是什么东西,有看文档精彩吗?

视频是什么东西,有看文档速度快吗?

视频是什么东西,有看文档效率高吗?


诸小亮:这一节,我们介绍一下其他不常用的流对象

张小飞:既然不常用,还学习他们干嘛?

诸小亮:虽然不常用,但是偶尔也会用到,技多不压身嘛

Properties

诸小亮:Properties——HashTable的子类,存储键值对,可以把数据持久化到硬盘上

张小飞:哦?这得见识一下

基本演示

诸小亮:它的使用也很简答

public static void main(String[] args) throws IOException {
    Properties prop = new Properties();
    //1. 存储
    prop.put("yase","19");
    prop.put("daji","16");
    prop.put("change","20");
    
    //2. 遍历
    Set<String> names = prop.stringPropertyNames();
    for(String name : names){
        System.out.println(name + "----" + prop.get(name));
    }
    //修改数据
	//prop.setProperty("daji","18");
}

结果:
image.png

诸小亮:需要注意,只有键值都是String时,能使用 stringPropertyNames,否则:

image.png 结果:image.png

image.png 结果:image.png

张小飞:明白了,不过,您不是说他能把数据持久化到硬盘上吗?

持久化数据

诸小亮:当然了,首先看它的 list 方法

  • list:可以把Properties中的数据放到一个 OutputStream 中
public static void main(String[] args) throws IOException {
    Properties prop = new Properties();
    //1. 存储
    prop.put("yase","18");
    prop.put("daji","16");
    prop.put("change","20");

    //把内容输出到System.out中
    prop.list(System.out);
}

结果:image.png 注意:** list 方法一般用于测试**

张小飞:不行,这还是没有保存到文件中

诸小亮:看你急的,使用 store 就能存储数据了

public static void main(String[] args) throws IOException {
    Properties prop = new Properties();
    //1. 存储
    prop.put("yase","18");
    prop.put("daji","16");
    prop.put("change","20");

    //2. 把内容输出到文件中
    FileOutputStream out = new FileOutputStream("G:\\learn\\hero.properties");
    
    //3. 第一个参数是OutputStream对象,第二个参数是备注
    prop.store(out,"hero info");

    out.close();
}

结果:image.png

image.png
张小飞:原来输出后,key 和 value 用等号连接了起来

诸小亮:是的,其实——properties是 Java 中最常用的配置文件格式

张小飞:那,现在学习 properties 配置文件吗?

诸小亮:no no no,等到学Java的高级框架时候,才会讲这个

读取properties文件

张小飞:既然存到文件中,那么肯定也能从文件中读取吧

诸小亮:当然可以,使用 load 方法

public static void main(String[] args) throws IOException {
    Properties prop = new Properties();
    FileInputStream in = new FileInputStream("G:\\learn\\hero.properties");
    
    //1. 加载properties文件
    prop.load(in);

    //2. 遍历
    Set<String> names = prop.stringPropertyNames();
    for(String name : names){
        System.out.println(name + "----" + prop.get(name));
    }
    in.close();
}

结果:image.png

PrintStream

张小飞:这个 PrintStream 是???

诸小亮:PrintStream——字节打印流,可以把各种类型数据打印到目的地

张小飞:目的地?不是输出到文件中吗?

诸小亮:目的地可以是——File、OutputStream 等对象,包含文件

张小飞:原来是这样

诸小亮:其实我们早就用过这个对象了

张小飞:嗯?什么时候用过?

诸小亮:我们常用的 System.out 就是打印流:

image.png

写入文件

诸小亮:我们先尝试使用 PrintStream 往文件中存储数据

public static void main(String[] args) throws IOException {
    //1. 创建对象,指定目的地,有两种方式:
    PrintStream printStream = new PrintStream("G:\\learn\\hero.txt");
//        PrintStream printStream = new PrintStream(new File("G:\\learn\\hero.txt"));

    //2. 写入字节数据
    printStream.write("yase".getBytes());
    //3. 关闭流
    printStream.close();
}

结果:image.png

常用方法

write

诸小亮:write(int b)——每次写入一个字节

PrintStream printStream = new PrintStream("G:\\learn\\hero.txt");

//写入字节数据
printStream.write(97);//97对应的是a
printStream.write(353);

//关闭流
printStream.close();

结果:image.png

张小飞:嗯,怎么会这样??????

诸小亮:因为每次只是写入参数的最后一个字节,具体原因:

结果是:aa
	第一个 a 是 97,第二个 a 对用35397的二进制是:00000000 00000000 00000000 01100001
353转换成二进制是:00000000 00000000 00000001 01100001

因为该方法每次只写入一个字节,97353的最后一个字节一样,所以。。。。。

张小飞:明白了,不过每次只写入一个字节,太扯淡了,不能用这个方法

诸小亮:不错,所以它有提供了另一个方法

write

write(byte b[]):写入字节数组中的所有数据

如果就是想写入 “97” 这两个字符,可以使用这个方法,比如:

image.png

结果:image.png

print

print:可以打印各种类型数据到目的地中

张小飞的Java之路——第四十四章——其他流对象_第1张图片

public static void main(String[] args) throws IOException {
    //创建对象时,指定目的地,常用的两种方式:
    PrintStream printStream = new PrintStream("G:\\learn\\hero.txt");

    //打印各种类型数据,println比print多换行功能
    printStream.println(true);
    printStream.println(97);
    printStream.println("yase");
    printStream.println(3.14);
    printStream.println('c');
    //关闭流
    printStream.close();
}

结果:image.png

PrintWriter

张小飞:不用说了,PrintWriter——肯定是字符打印流,跟 PrintStream 类似

诸小亮:是的,它们的区别在于——PrintWriter 的 write 方法可以直接写入字符串

image.png

ObjectOutputStream

诸小亮:ObjectOutputStream——把 java 对象写入到文件中,称之为:序列化

张小飞:哦?怎么把对象写到文件中?

诸小亮:来,看下面的代码

class Hero {
    String name;
    public Hero (String name){
        this.name = name;
    }
    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                '}';
    }
}

public static void main(String[] args) throws IOException {
    //1. 目的地
    FileOutputStream out = new FileOutputStream("G:\\learn\\hero.txt");
    //2. 使用ObjectOutputStream封装FileOutputStream
    ObjectOutputStream objOut = new ObjectOutputStream(out);

    //3. 写入java对象
    Hero hero = new Hero("yase");
    objOut.writeObject(hero);

    //4. 关闭流
    objOut.close();
}

结果:

image.png

张小飞:您这不是报错了吗?

诸小亮:这时因为 Hero 对象没有实现 Serializable 接口,所以不能序列化

张小飞:Serializable 是什么?

诸小亮:Serializable——序列化标识接口,该接口没有任何方法

image.png

诸小亮:但是只有实现Serializable接口的类,才能序列化

张小飞:明白了

诸小亮:修改Hero类,让其实现 Serializable
image.png

张小飞:我又运行了一些,虽然没有报错,但是文件打开是这样子的

image.png

诸小亮:因为 java 对象不是文本数据,所以使用记事本打开会乱码

ObjectInputStream

诸小亮:ObjectInputStream——从文件中读取对象,称之为:反序列化

public static void main(String[] args) throws IOException, ClassNotFoundException {
    //目的地
    FileInputStream in = new FileInputStream("G:\\learn\\hero.txt");
    ObjectInputStream objIn = new ObjectInputStream(in);

    //从文件中读取对象
    Hero o = (Hero) objIn.readObject();
    System.out.println(o.toString());
}

结果:

image.png

张小飞:怎么又报错了? Hero 不是已经实现了 Serializable 接口了吗?

诸小亮:这时因为,缺少一个静态变量serialVersionUI

张小飞:这是????

诸小亮:serialVersionUID: 序列化的版本号,实现Serializable接口,都应该有个这样的静态变量
image.png

注意:变量的值随意
再次序列化后,再次读取image.png

transient

张小飞:transient 是什么意思?

诸小亮:transient——瞬态关键字,瞬态:瞬间状态

张小飞:这是干什么的?

诸小亮:如果有些字段不想被序列化到文件中,可以使用这个修饰符,比如:

image.png

张小飞:您的意思是,这样 name 字段就不会序列化的文件中了?

诸小亮:是的,使用 transient 后,name字段只存在于内存中,不会被写到文件中

再次运行 序列化 和 反序列化,结果:

image.pngimage.png

ByteArrayInputStream 和 ByteArrayOutputStream

张小飞:这是——字节数组–输入输出流?

诸小亮:是的,其实就是用 IO 的读写思想,操作数组

  • ByteArrayInputStream :字节数组输入流,是InputStream的子类

张小飞:什么意思?

诸小亮:之前都是从文件中读取数据,而ByteArrayInputStream,从是字节数组中读取

image.png
张小飞:明白了,所以创建对象时,要传递一个字节数组进去

诸小亮:是的,另外还有 ByteArrayOutputStream

  • ByteArrayOutputStream :字节数组输出流,是 OutputStream 的子类
  • 作用:把数据写到其内部的一个 byte 数组中

张小飞:那是一个可变数组吧

诸小亮:不错,内部的数组会随着数据的不断写入而自动增长

张小飞:能演示一下吗?

诸小亮:当然可以

public static void main(String[] args) throws IOException, ClassNotFoundException {
    ByteArrayInputStream bin = new ByteArrayInputStream("yase".getBytes());
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    int ch =0;
    //从ByteArrayInputStream读出,写到ByteArrayOutputStream中
    while((ch = bin.read()) != -1){
        //写入内部数组中
        bout.write(ch);
    }
    //获取ByteArrayOutputStream中的数据
    System.out.println(bout.toString());
}

张小飞:您没有关闭流对象

诸小亮:这两对象操作的都是内存,比较特殊,所以不用close

张小飞:明白了

你可能感兴趣的:(java,servlet,jvm)