就业班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的输出
|
|