A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨纯纯 初级黑马   /  2018-11-26 17:18  /  638 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

缓冲流 转换流 序列化流 打印流
IO流:
    缓冲流: BufferedInputStream / BufferedOutputStream, BufferedReader / BufferedWriter
        在基本流上增加缓冲区 char[] byte[], 提高读写效率
    转换流: InputStreamReader / OutputStreamWriter
            字节转字符: FileReader 读 char <- byte 硬盘
                字符转字节: FileWriter 写 char -> byte 硬盘
    序列化流: ObjectInputStream / ObjectOutputStream
            序列化:   内存中的对象 写-> 硬盘上的文件中
        反序列化: 内存中的对象 <-读 硬盘上的文件中
    打印流: PrintStream
            可以自动换行, 原样输出  System.out.println();

基本流: FileXxx
包装流:
        包装流只是在基本流的外面增加了一些便捷的功能, 最终进行读写的还是基本流
        但是包装流增强了基本流的功能
        BufferedReader br = new BufferedReader(new FileReader());

缓冲流的原理:
        底层也是使用基本流(FileXxx)来读写
        但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了程序效率

缓冲字节输出流: BufferedOutputStream
字节缓冲流
        |_ BufferedInputStream     # 缓冲字节输入流
        |_ BufferedOutputStream    # 缓冲字节输出流

字符缓冲流
        |_ BufferedReader          # 缓冲字符输入流
        |_ BufferedWriter          # 缓冲字符输出流
       
java.io.BufferedOutputStream类: 缓冲字节输出流
        // 构造方法
        BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
        BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
       
BufferedOutputStream使用步骤:
        1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地
        2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象
        3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
        4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
        5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)
        
        FileOutputStream fos = new FileOutputStream("文件路径");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bos.write("你好".getBytes());
        // bos.flush();  // 可以省略
        bos.close();
缓冲字符输出流: BufferedWriter:
BufferedWriter如何创建对象
BufferedWriter特有的写入换行符方法好处是什么?
java.io.BufferedWriter类:
        // 构造方法
        BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
        BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
        // 特有方法
        void newLine(): 写入一个换行符, 换行符自动根据当前系统确定


什么是编码
什么是解码
字符集和编码表有什么区别
常见的编码表有哪些

编码: 字符 -> 字节  'a' -> 97
解码: 字节 -> 字符  97 -> 'a'

编码表: 字符和二进制数字的对应规则

字符集和编码表: 字符集包含编码表
        ASCII字符集
                ASCII编码表
                ASCII扩展编码表
        ISO-8859-1字符集: Tomcat Web服务器程序
                Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成
        GB字符集
                GB2312编码表: 每个字符由2个byte组成
                GBK编码表: 每个字符由2个byte组成
                GB18030编码表: 每个字符由1, 2, 4个byte组成
        Unicode字符集
                UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, Unicode辅助字符占4个byte
                UTF-16
                UTF-32
        ANSI: 表示使用系统默认编码表

IDEA是 UTF-8 编码, 在IDEA中使用FileReader读取GBK编码的文件, 能否读到正确的中文
乱码产生的原因是什

乱码原因: 读写编码不一致
        GBK文件中存储的是"你好"在GBK中对应的byte
        而IDEA中使用FileReader读取文件时, 是将byte按照UTF-8编码表查找字符, 结果找不到, 就显示了问号

FileReader和InputStreamReader有什么关系
FileWriter和OutputStreamWriter有什么关系
转换流有什么作用

java.io.Reader
        |_ InputStreamReader: 转换字符输入流      byte --查指定码表--> char, char[], String
                |_ FileReader                       byte --查UTF-8码表--> char
java.io.Writer
        |_ OutputStreamWriter: 转换字符输出流      char, char[], String --查指定码表--> byte
                |_ FileWriter                        char --查UTF-8码表--> byte
OutputStreamWriter类介绍及使用
创建OutputStreamWriter对象时, 如何指定使用的编码表
java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
        // 构造方法
        OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
        OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流


// 使用默认UTF-8
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));
o.write("dsfdsfdsaf")

// 使用指定的GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
                osw.write("你") -> 查"GBK"码表 -> -1,-2 -> FileOutputStream -> a.txt文件
         写数据: 字符流 --------------------------> 字节流
创建InputStreamReader对象时, 如何指定使用的编码表
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
        // 构造方法
        InputStreamReader(InputStream in): 使用默认编码表创建转换流
        InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流

// 使用默认UTF-8
InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"));

// 使用指定的GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
     '你' <- 查"GBK"码表 <- isr.read() <- -1,-2 <- FileInputStream <- a.txt文件
                         读数据: 字符流 <---------- 字节流       


什么是序列化
什么是反序列化

序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中
        对象 -> 字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象
        字节 -> 对象

通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态

OutputStream
        |_ ObjectOutputStream类: 对象字节输出流
InputStream
        |_ ObjectInputStream类: 对象字节输入流

ObjectOutputStream如何创建对象
调用什么方法将对象写入到文件
[重要!] 被序列化的对象所属的类, 有什么特殊的要求

java.io.ObjectOutputStream类: 对象字节输出流
        // 构造方法
        ObjectOutputStream(OutputStream out)
        // 特有成员方法
        void writeObject(Object obj): 将对象写出

// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18);
oos.writeObject(s);
// 释放资源
oos.close();

注意:
        被读写的对象的类必须实现"java.io.Serializable"接口, 否则会抛出"NotSerializableException"


ObjectInputStream如何创建对象
ObjectInputStream如何将对象从文件中读取到程序中
ava.io.ObjectInputStream类: 对象字节输入流
        // 构造方法
        ObjectInputStream(InputStream in)
        // 特有成员方法
        Object readObject(): 读取对象

// 创建对象输入流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));
// 读对象
Object o = oos.readObject();
Student s = (Student)o;
System.out.println(s);
// 释放资源
oos.close();

如果将对象序列化到文件中后, 代码中的类发生了变化, 能否正常反序列化文件中的对象?
[重要!]"InvalidClassException"什么情况下发生, 如何避免

public class Person {
    int age;
}

oos.writeObject(new Person("张三", 13));
Object p = ois.readObject();

serialVersionUID序列号的作用:
        序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
        该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化
        当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException

为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的



补充: IDEA设置生成序列版本号:
Setting -> Editor -> Inspections -> Java -> Serialization issues -> 勾选Serializable class without 'serialVersionUID'













0 个回复

您需要登录后才可以回帖 登录 | 加入黑马