更强大的流
- 高效读写的缓冲流
- 转换编码的转换流
- 持久化存储对象的序列化流
- 读取文件中对象的反序列化流
- 只读不写、自动刷新、自动换行的打印流
使用这些更强大的流对字节流与字符流进行包裹,使其可以调用更多的方法,更加便捷、快速地完成需求。
1. 缓冲流
1.1 缓冲区与缓冲流
1.1.1 缓冲区:
缓冲区是开辟的一个内存缓冲区的内存区域。
计算器访问外部设备或文件,相比直接访问内存慢很多。在调用read()或write()方法时,CPU需花费更多时间等待外部设备响应,而不是直接进行数据处理。
调用read()或write()方法时先使用缓冲区。在这个缓冲区装满后,系统将缓冲区中的内容一次集中读取或写出。有效提高了CPU的使用率,大大促进了计算机系统的效率,使程序更快的完成任务。
字符流自带缓冲区,会将文件中数据尽可能多的放入缓冲区。
1.1.2 缓冲流:
拥有缓冲区的流叫做缓冲流。
使用缓冲区的流工作效率会比直接读取文件或者写出文件的流效率高很多。
缓冲流将数据从原始流成块读入或把数据积累到一个大数据块后再成批写出,通过减少通过资源的读写次数加快了程序的执行。
缓冲流有四种:
字节缓冲输入流:BufferedInputStream
字节缓冲输出流:BufferedOutputStream
字符缓冲输入流:BufferedReader
字符缓冲输出流:BufferedWriter
1.2 补充:
- 缓冲流可显著提高字节流的读写性能。
- 字符流自带缓冲区故对字符流的提升并不明显,但字符缓冲流中有两个重要方法:
方法返回值 方法名 作用 String readLine() BufferedReader中使用,读取一个文本行 Void newLine() BufferedWriter中使用,写出一个行分隔符 这两种方法使自带缓冲区的字符流有了使用字符缓冲流的必要性。
2. 转换流
2.1 解码和编码:
计算机中存储的信息都是由二进制表示的,将我们理解的字符(生活中的文字)转化为不理解的字节的过程称为编码,将我们不理解的字节转化为理解的字符的过程称为解码。
我们编码和解码应使用同一个码表,同一个解码方式,否则可能就会出现乱码现象。
举例:
Windows创建的文本文档默认是GBK编码,而使用idea读取时,因为idea默认为UTF-8的编码方式,就会导致阅读到一堆乱码。
此时就可以使用转换流,将A编码方式的文件转换为B编码方式的文件,是对其编码方式的改变。
转换流有两种:
类名 InputStreamReader 字符转换输入流 OutputStreamWriter 字符转换输出流
2.2 类 InputStreamReader
将字节输入流转换为字符输入流。
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的字符集(charset)读取字节(获取到的是字节),并将其解码为字符。
2.2.1 构造方法:
方法参数 | 作用 |
---|---|
InputStreamReader(InputStream in) | 创建使用默认字符集的对象 |
[InputStreamReader](…/…/java/io/InputStreamReader.html#InputStreamReader(java.io.InputStream, java.nio.charset.Charset))(InputStream in, Charset cs) | 创建使用给定字符集(软件中提供)的对象 |
[InputStreamReader](…/…/java/io/InputStreamReader.html#InputStreamReader(java.io.InputStream, java.lang.String))(InputStream in, String charsetName) | 创建使用指定字符集(字符串表示)的对象 |
[InputStreamReader](…/…/java/io/InputStreamReader.html#InputStreamReader(java.io.InputStream, java.nio.charset.CharsetDecoder))(InputStream in, CharsetDecoder dec) | 创建使用给定字符集解码器的字符集 |
2.2.2 常用成员方法:
返回值 | 方法名 | 作用 |
---|---|---|
int | read() | 读取单个字符 |
int | [read](…/…/java/io/InputStreamReader.html#read(char[], int, int))(char[] chars, int offset, int length) | 读取字符数组中的一部分 |
void | close() | 关闭该流并释放与之关联的所有资源 |
2.3 类 OutputStreamWriter
将字节输出流转换为字符输出流。
OutputStreamWriter 是字符流通向字节流的桥梁:它使用指定的字符集(charset)将要写入流中的字符编码成字节。
2.3.1 构造方法:
方法参数 | 作用 |
---|---|
OutputStreamWriter(OutputStream out) | 创建使用默认字符集的对象 |
[OutputStreamWriter](…/…/java/io/OutputStreamWriter.html#OutputStreamWriter(java.io.OutputStream, java.nio.charset.Charset))(OutputStream out, Charset cs) | 创建使用给定字符集(软件中提供)的对象 |
[OutputStreamWriter](…/…/java/io/OutputStreamWriter.html#OutputStreamWriter(java.io.OutputStream, java.lang.String))(OutputStream out, String charsetName) | 创建使用指定字符集(字符串表示)的对象 |
[OutputStreamWriter](…/…/java/io/OutputStreamWriter.html#OutputStreamWriter(java.io.OutputStream, java.nio.charset.CharsetEncoder))(OutputStream out, CharsetEncoder enc) | 创建使用给定字符集编码器的字符集 |
2.3.2 常用成员方法:
返回值 | 方法名 | 作用 |
---|---|---|
void | write(int c) | 写入单个字符 |
void | [write](…/…/java/io/OutputStreamWriter.html#write(char[], int, int))(char[] chars, int off, int len) | 写入字符数组的一部分 |
void | [write](…/…/java/io/OutputStreamWriter.html#write(java.lang.String, int, int))(String str, int off, int len) | 写入字符串的一部分 |
void | flush() | 刷新该流的缓冲 |
void | close() | 关闭流(关闭之前要刷新) |
2.4 转换流的作用
- 指定字符集读写数据(jdk11后已淘汰)。
- **字节流想要使用字符流中的方法:**使用后字节流对象可以使用字符流中的方法,可以直接对字符进行读取和写出的操作。
3. 序列化流
序列化流也叫“对象操作输出流”,可以将Java中的对象写出至本地文件中。
3.1 类 ObjectOutputStream
使用此类包裹指定的OutputStream ,即可调用序列化流的方法。
3.1.1 常用成员方法
返回值 | 方法名 | 作用 |
---|---|---|
void | writeObject(Object obj) | 将指定的对象写入 ObjectOutputStream |
void | close() | 关闭流 |
4.反序列化流
反序列化流也叫“对象操作输入流”,可以把序列化到本地文件中的对象读取至程序中。
4.1 类 ObjectInputStream
使用此类包裹指定的InputStream ,即可调用序列化流的方法。
4.1.1 常用成员方法
返回值 | 方法名 | 作用 |
---|---|---|
object | readObject() | 从 ObjectInputStream 读取对象 |
void | close() | 关闭流 |
3/4. 细节问题
- 一个Javabean类有一个序列号,对其修改后会更新序列号,
序列化与反序列化时,Javabean类序列号需相同,否则会报错。
可先固定其序列号:
private static final long serialVersionUID = 1L;
也可使用Idea中自带的工具生成序列号(随机生成,序列号更专业),并将其固定。
- 序列化流写到文件中的数据不能修改,修改后无法再读回来。
- 某一成员变量不想被序列化,可以用transient关键字修饰,该成员变量不参与序列化过程。
5.打印流
一般指:类 PrintStream与类 PrintWriter。
特点:
- 只操作目的地,不操作数据源,故只写不读。
- 特有的写出方法,可以实现数据原样写出。
- 特有的写出方法,可以自动刷新,自动换行,(打印一次数据 = 写出 + 换行 + 刷新)。
字符流底层有缓冲区,想要自动刷新需要开启;
字节打印流自动刷新(默认)。
5.1 PrintStream
包裹字节输出流。
5.1.1 常用成员方法使用实例:
//1.创建字节打印流的对象
PrintStream ps = new PrintStream(new FileOutputStream("myio\\a1.txt"), true, "UTF-8");
//2.写出数据
ps.println(97); //写出"97"
ps.print(true);
ps.println();
ps.printf("%s爱上了%s", "阿珍", "阿强");
//3.释放资源
ps.close();
5.2 PrintWriter
包裹字符输出流。
5.2.1 常用成员方法使用实例:
//1.创建字符打印流的对象
PrintWriter pw = new PrintWriter(new FileWriter("myio\\a1.txt"), true);
//2.写出数据
pw.println("吃早饭了吗");
pw.print(true);
pw.println();
pw.printf("%s人独立,%s燕双飞", "落花","微雨");
//3.释放资源
pw.close();