JavaIO流-特殊操作流

一、特殊操作流

1.1、标准输入输出流

  • System 类中有两个静态的成员变量:
    • public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
    • public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标。

1.1.1、标准输入流

  • public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源。
//        // 标准输入流
//        InputStream is = System.in;
//
////        // 一次输入一个字节
////        int by;
////        while ((by=is.read())!=-1){
////            System.out.println((char)by);
////        }
//
//        // 把字节流转换为字符流
//        InputStreamReader isr = new InputStreamReader(is);
//        // 使用字符缓冲输入流 可以一次读取一行数据
//        BufferedReader br = new BufferedReader(isr);

// 以上代码简化为 一行
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.println("请输入一个字符串:");
String line = br.readLine();
System.out.println("你输入的字符串是:"+line);

System.out.println("请输入一个整数:");
int i = Integer.parseInt(br.readLine());
System.out.println("你输入的整数是:"+i);

// 释放资源
br.close();
// Java 提供的键盘输入
Scanner sc = new Scanner(System.in);

1.1.2、标准输出流

  • public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标。
  • 输出语句的本质:是一个标准的输出流
// 标准输出流
PrintStream ps = System.out;

//        // 能够方便地打印各种数据值
//        ps.print("hello");
//        ps.print(100);
//
//        ps.println("hello");
//        ps.println(100);

// System.out 的本质是一个字节输出流
System.out.println("hello");
System.out.println(100);

1.2、打印流

  • 打印流分类:
    • 字节打印流:PrintStream
    • 字符打印流:PrintWriter
  • 打印流的特点:
    • 只负责输出数据,不负责读取数据
    • 有自己的特有方法

1.2.1、字节打印流

  • PrintStream(String fileName):使用指定的文件名创建新的打印流。
  • 使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出。
// 使用指定的文件名创建新的打印流
PrintStream ps = new PrintStream(".\\a.txt");

// 写数据
// 字节输出流有的方法
ps.write(97);   // 转换为 a
// 使用特有方法写数据
ps.println(97);   // 直接写入 97

// 释放资源
ps.close();

1.2.2、字符打印流

  • 字符打印流 PrintWriter 的构造方法:
方法名 说明
PrintWriter(String fileName) 使用指定的文件名创建一个新的 PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out,boolean autoFlush) 创建一个新的PrintWriter,out:字符输出流,autoFlush:一个布尔值,如果为真,则println,print 或 format 方法将刷新输出缓冲区
// PrintWriter(String fileName)
PrintWriter pw = new PrintWriter(".\\a.txt");
pw.write("中国\n");
pw.flush();

pw.println("hello");
pw.flush();

pw.format("java");
pw.flush();
pw.close();

// PrintWriter(Writer out,boolean autoFlush)
PrintWriter pw = new PrintWriter(new FileWriter(".\\a.txt"),true);
pw.write("中国\n");


pw.println("hello");

pw.format("java");

pw.close();

1.3、对象序列化流

  • 对象序列化:就是将对象保存到磁盘中,或者在网路中传输对象。
  • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息字节序列写到文件之后,相当于文件中持久保存了一个对象的信息。
  • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。

1.3.1、对象序列化流

  • 对象序列化流:ObjectOutputStream

    • 将 Java 对象的原始数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
  • 构造方法:

    • ObjectOutputStream​(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream。
  • 序列化对象的方法:

    • void writeObject​(Object obj):将指定的对象写入ObjectOutputStream。
  • 注意:

    • 一个对象要想被序列化,该对象所属的类必须实现 Serializable 接口
    • Serializable 是一个 标记接口,实现该接口,不需要重写任何方法
// 测试类

public static void main(String[] args) throws IOException {
    // 创建 对象序列化流 的对象
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(".\\a.txt"));
    // 创建对象
    Student s1 = new Student("林青霞", 30);

    // 把对象序列化
    oos.writeObject(s1);

    // 释放资源
    oos.close();

}
// 学生类

import java.io.Serializable;
// 不实现 Serializable 接口的类将不会使任何状态序列化或反序列化
public class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }
}

1.3.2、对象反序列化流

  • 对象反序列化流:ObjectInputStream

    • ObjectInputStream 反序列化先前使用 ObjectOutputStream 编写的原始数据和对象
  • 构造方法:

    • ObjectInputStream(InputStream in):创建从指定的 InputStream 读取的 ObjectInputStream。
  • 反序列化对象的方法:

    • Object readObject​():从 ObjectInputStream 读取一个对象。
public static void main(String[] args) throws IOException, ClassNotFoundException {
    // 创建 对象反序列化流 对象
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(".\\a.txt"));
    // 使用对象反序列化流的方法
    Object obj = ois.readObject();

    // 向下转型
    Student s = (Student) obj;
    System.out.println(s.getName()+", "+s.getAge());

    // 释放资源
    ois.close();
}

1.3.3、对象序列化的问题

1.3.3.1、修改源类文件的问题

  • 用对象序列化流序列化了一个对象后,修改了对象所属的类文件,读取数据会报该异常:

    • InvalidClassException
  • 解决方法:

    • 给对象所属的类加一个 serialVersionUID :
      • private static final long serialVersionUID = 42L;
import java.io.Serializable;
// 不实现 Serializable 接口的类将不会使任何状态序列化或反序列化
public class Student implements Serializable {
    private static final long serialVersionUID = 42L; // 初始化 serialVersionUID 这样就不会报异常
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }
}

1.3.3.2、设置某个成员变量不被序列化

如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

transient 修饰的不会被序列化

import java.io.Serializable;
// 不实现 Serializable 接口的类将不会使任何状态序列化或反序列化
public class Student implements Serializable {
    private static final long serialVersionUID = 42L;
    private String name;
//    private  int age;
    private transient int age;

    public Student() {
        System.out.println();
    }

    public Student(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;
    }   
}

1.4、Properties

1.4.1、Properties 概述

  • 是一个 Map 体系的集合类
  • Properties 可以保存到流中或从流中加载

1.4.2、Properties 的使用

// 创建集合对象
Properties prop = new Properties();

// 存储元素
prop.put("001","林青霞");
prop.put("002","张曼玉");
prop.put("003","王祖贤");

// 遍历集合
Set<Object> keySet = prop.keySet();
for (Object key : keySet){
    Object value = prop.get(key);
    System.out.println(key + ", " + value);
}

1.4.3、Properties 的方法

方法名 说明
Object setProperty(String key,String value) 设置集合的键和值,都是 String 类型,底层调用 Hashtable 方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串

1.4.3.1、setProperty(String key,String value) 方法

  • 设置集合的键和值,都是 String 类型,底层调用 Hashtable 方法 put。
// 创建集合对象
Properties prop = new Properties();
// 添加元素
prop.setProperty("001","林青霞");
prop.setProperty("002","张曼玉");
prop.setProperty("003","王祖贤");

// 打印集合
System.out.println(prop);

1.4.3.2、getProperty(String key) 方法

  • 使用此属性列表中指定的键搜索属性。
// 创建集合对象
Properties prop = new Properties();
// 添加元素
prop.setProperty("001","林青霞");
prop.setProperty("002","张曼玉");
prop.setProperty("003","王祖贤");

// 输出 集合键所对应的 值
System.out.println( prop.getProperty("002") );

// 打印集合
System.out.println(prop);

1.4.3.3、Set<String> stringPropertyNames()

  • 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串。
// 创建集合对象
Properties prop = new Properties();
// 添加元素
prop.setProperty("001", "林青霞");
prop.setProperty("002", "张曼玉");
prop.setProperty("003", "王祖贤");

// 获取集合的键 并遍历
Set<String> names = prop.stringPropertyNames();
for (String key : names) {
    String value = prop.getProperty(key);
    System.out.println(key + ", " + value);
}

1.4.4、Properties 和 IO 流结合的方法

方法名 说明
void load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(OutputStream out,String comments) 将此属性列表(键和元素对)写入此 Properties 表中,以适合于使用 load(InputStream) 方法的格式写入输出字节流
void store(Writer writer,String comments) 将此属性列表(键和元素对)写入此 Properties 表中,以适合使用 load(Reader) 方法的格式写入输出字符流

1.4.4.1、load() 方法

// 创建 Properties 集合对象
Properties prop = new Properties();

// 创建字符缓冲输入流
FileReader fr = new FileReader(".\\a.txt");
// 从输入字符流读取属性列表
prop.load(fr);
// 释放资源
fr.close();

// 打印集合
System.out.println(prop);

1.4.4.2、store() 方法

// 创建 Properties 集合对象
Properties prop = new Properties();

// 向集合中添加元素
prop.setProperty("001","林青霞");
prop.setProperty("002","张曼玉");
prop.setProperty("003","王祖贤");

// 创建字符缓冲输出流
FileWriter fw = new FileWriter(".\\a.txt");

// 以适合使用 load(Reader) 方法的格式写入 字符流输出流
prop.store(fw,null);
fw.close();
posted @ 2021-02-20 16:04    阅读(67)  评论(0)    收藏  举报