黑马程序员技术交流社区

标题: [石家庄校区]就业班JavaSE高级部分day10 缓冲流 转换流 序列... [打印本页]

作者: 湿漉漉的文字控    时间: 2018-11-26 16:02
标题: [石家庄校区]就业班JavaSE高级部分day10 缓冲流 转换流 序列...
就业班JavaSE高级部分day10 缓冲流 转换流 序列化流 打印流
基本流:
Filexxx
包装流:
在基本流的外面增加一些便捷功能,最终读写的还是基本流,包装流只增强的
基本流的功能
缓冲流:
BufferedOutputStream:字节缓冲输出流
extents OutputStream
能够使用子类的共用方法
格式
BufferedOutputStream bos = new BufferedOutputStream(OutputStream   
out)
BufferedInputStream::字节缓冲输入流
extents InputStream
能够使用子类的共用方法
格式
BuffInputStream bis = new BuffInputStream(InputStream in)
BuffWriter:字符缓冲输出流
extends Writer
能够使用子类共用的方法
特有方法:
void newLine(); 写入一个行分隔符,根据不同的操作系统,获取不同的行分隔符
格式
BufferedWriter bw = new BufferedWriter(Writer out);
BufferedReader:字符缓冲输入流
extends Reader
能够使用子类共用的方法
特有方法:
String readLine();一次读取一行字符串,(遇行的终止符号即停止)不包括换行符,返回
值为null.
格式:
BufferedReader br = new BufferedReader(Reader in);
案例:把文件中的段落排序
步骤分析:
        1. 创建ArrayList集合, 泛型用String
        2. 创建BufferedReader对象, 构造方法中传递FileReader对象, 指向模块下的in.txt
        3. 创建BufferedWriter对象, 构造方法中传递FileWriter对象, 指向模块下的out.txt
        4. 使用BufferedReader对象中的方法readLine, 以行的方式读取文本
        5. 把读取到的文本存储到ArrayList集合中
        6. 使用Collections集合工具类的方法sort, 对集合中的元素按照自定义规则排序
        7. 遍历ArrayList集合, 获取每一个元素
        8. 使用BufferedWriter对象中的方法write, 把遍历得到的元素写入到文本中(内存缓冲区)
        9. 写换行
       10. 释放资源
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test5 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("day10\\in.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("day10\\out.txt"));
        //创建一个集合 用来存储读出来的数据 和进行排序
        ArrayList<String> list = new ArrayList<>();
        //调用BufferedReader对象中的readLine方法一次读取一行 创建一个变量用来接收read出来的值
        String line;
        while ((line = br.readLine()) != null) {
            //把的出来的line 放到集合中
            list.add(line);
        }
        //根据首字符正序排序
        //Collections.sort(list, (o1, o2) -> o1.charAt(0) - o2.charAt(0));
        list.sort((o1, o2) -> o1.charAt(0) - o2.charAt(0));
        //遍历集合放到out文件中
        for (String s : list) {
            //写入文件
            bw.write(s);
            //写入不包括换行符所以调用newLine换行
            bw.newLine();
        }
        //释放资源
        bw.close();
        br.close();
    }
}
转换流:
编码:字符(能看懂)-->字节(不能看懂)
解码:字节(看不懂)-->字符(能看懂)
字符编码
是一套自然语言的字符与二进制之间的对应规则
乱码问题:
原因:
读写编码不一致
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
案例:
需求:
使用转换流, 读取GBK编码文件"我是GBK文件.txt"中的"你好", 转写到UTF-8编码文件"我是
UTF8文件.txt"中, 保证UTF-8文件打开也能看到正确的中文
分析:
        GBK编码文件中保存的字符, 是根据GBK查询到的byte. UTF-8文件中, 要写入根据UTF-
8查到的byte
                GBK"你好"的byte --> 按GBK读 --> "你好" --> 按UTF-8写 --> UTF-8"你好"的byte
                               InputStreamReader      OutputStreamWriter
                                   read()                 write()       
        使用InputStreamReader读取GBK编码文件时, 需要指定编码为GBK
        使用OutputStreamWriter将读取到的字符, 按照UTF-8写入到UTF-8编码文件
        边读边写类似于复制文件
        释放资源
代码:
public class Test {
    public static void main(String[] args) throws IOException {
        // 创建转换输入流对象, 指向GBK文件, 同时指定按照GBK来读取
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day10\\我是GBK.txt"), "GBK");
        // 创建转换输出流对象, 路径填写utf8文件, 同时指定按照UTF-8来写
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day10\\我是UTF8文件.txt"), "UTF-8");
        // 循环读写: 类似于文件复制, 一次读写一个字符
        int ch;
        while ((ch = isr.read()) != -1) {
            // 读到一个写一个
            osw.write(ch);
        }
        // 刷新缓冲区并释放资源
        osw.close();
        isr.close();
    }
}
对象序列化流: 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
java.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();
transient瞬态关键字: 避免属性序列化
static 修饰的成员变量属于类不属于对象, 所以不能序列化
transient 修饰的成员变量, 不能被序列化

transient 应用场景:
        如果对象的某个属性不希望被序列化, 可以使用 transient 修饰, 这样就不会被对象流写到文件中
InvalidClassException异常: 原因和解决方案
serialVersionUID序列号的作用:
        序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
        该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会
发生变化
        当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException
为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是
一样的
打印流PrintStream: 概述和使用

PrintStream特点:
    1. 只有输出流, 没有输入流
    2. PrintStream不会抛出IOException
    3. 有特殊方法 print(), println(), 可以输出任意类型的值, 原样输出

java.io.PrintStream类: 字节打印流
    // 构造方法
    PrintStream(File file): 创建字节打印流, 输出到一个文件
    PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
    PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
   
注意事项:
    如果用 write(97) 方法, 会查编码表   97 -> a
    如果用 print(97), println(97), 则原样输出  97 int -> '9''7' -> byte -> 文件 97
    System.out.println();
    PrintStream out;
   
java.lang.System类:
    // 静态方法
    static void setOut(PrintStream out): 设置System.out的输出






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2