目录
Buffered字符处理流(BufferedReader和BufferedWriter):
Buffered字节处理流(BufferedInputStream和BufferedOutputStream) :
ObjectOutputStream和ObjectInputStream:
在Java中的流,还分为字节流和处理流
节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
2.处理流(也叫包装流)是“连接"在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter
看下图:

节点流就是通过不同的方式去访问不同的数据源 ,比如文件就用文件流访问,数组就用数组流访问。
而包装流就是将这些节点流进行整合包装,提供一个更为完整的读写功能体系。
具体包装流是如何实现的,这就涉及到了一种涉及模式:拟修饰器设计模式。
具体不好描述,看视频 BV15B4y1u7Rn P12节。
BufferedReader 和BufferedWriter属于字符流,是按照字符来读取数据的
关闭时,只需要关闭外层流即可
可以引用所有的Read子类,包括文件、数组、管道等
这里读取了story.txt文件,里面存放了之前使用输入输出流copy文件的代码
- package com.io.reader;
-
-
- import java.io.BufferedReader;
- import java.io.FileReader;
-
- /**
- * @author 华子
- * bufferedReader的使用
- */
- public class BufReader {
- public static void main(String[] args) throws Exception {
- String filePath = "e:\\story.txt";
- BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
- String line = " ";
- while((line = bufferedReader.readLine())!=null){
- System.out.println(line);
- }
- bufferedReader.close();
- }
-
- }
这里还可以进行按行读取。
运行结果:

它同样也可以引用Writer里的所有子类。
- package com.io.writer;
-
- import java.io.BufferedWriter;
- import java.io.FileWriter;
-
- /**
- * @author 华子
- * bufferedWriter的使用
- */
- public class BufWriter {
- public static void main(String[] args) throws Exception{
- String filePath = "e:\\ok.txt";
- BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
- bufferedWriter.write("Hello,郑仲华");
- bufferedWriter.newLine();
- bufferedWriter.write("Hello,郑仲华");
- bufferedWriter.newLine();
- bufferedWriter.write("Hello,郑仲华");
- bufferedWriter.newLine();
- bufferedWriter.close();
- }
- }
很简单的代码,创建一个文件,写入数据 。(实现了换行nextLine)
BufferedReader和BufferedWriter拷贝文本文件:
- package com.io.writer;
-
- import java.io.*;
-
- /**
- * @author 华子
- * 使用BufferedReader和BufferedWtriter进行文件拷贝
- */
- public class BufCopy {
- public static void main(String[] args) throws Exception{
- String filePath01 = "e:\\story.txt";
- String filePath02 = "d:\\news.txt";
- String line = "";
- BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath01));
- BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath02));
- while ((line = bufferedReader.readLine())!=null){
- bufferedWriter.write(line);
- bufferedWriter.newLine();
- }
- System.out.println("拷贝成功...");
- if(bufferedReader!=null){
- bufferedReader.close();
- }
- if(bufferedWriter!=null){
- bufferedWriter.close();
- }
- }
- }
因为这两兄弟属于字符流,无法读取二进制文件(图片,视频,音乐等)
用法和字符处理流类似。
使用BufferedInputStream和BufferedOutputStream拷贝二进制文件:
- package com.io.outputstream_;
-
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
-
- /**
- * @author 华子
- * BufferedInputStream和BufferedOutputStream拷贝二进制文件(图片、视频、音乐)
- * 字节流BufferedInputStream和BufferedOutputStream也可以用于操作文本文件
- */
- public class BufCopy02 {
- public static void main(String[] args) throws Exception{
- String srcFilePath = "e:\\demo.mp4";
- String destFilePath = "d:\\demo.mp4";
- int readLen = 0;
- byte[] buf = new byte[1024];
- BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
- BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
- while((readLen = bufferedInputStream.read(buf))!=-1){
- bufferedOutputStream.write(buf,0,readLen);
- }
- System.out.println("拷贝成功...");
- if (bufferedInputStream != null){
- bufferedInputStream.close();
- }
- if (bufferedOutputStream != null){
- bufferedOutputStream.close();
- }
- }
- }
再看处理流之前,首先要搞懂两个概念。
1.序列化就是在保存数据时, 保存数据的值和数据类型
2.反序列化就是在恢复数据时,恢复数据的值和数据类型
3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
类必须实现如下两个接口之一 :Serializable(是一个标记接口)或者Externalizable。
大多数情况下都使用第一种接口,因为第二种接口需要实现方法。
大概图解:

接下来就是两种对象处理流:
ObjectOutputStream 提供序列化功能
ObjectInputStream 提供反序列化功能
看代码:
- package com.io.outputstream_;
-
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.ObjectOutputStream;
-
- /**
- * ObjectOutputStream 序列化数据
- */
- public class ObjOutputStream {
- public static void main(String[] args) throws IOException {
- String filePath = "e:\\data.dat";
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
- // 序列化数据
- oos.writeInt(100);//这里实现了自动装箱 int -->Integer(实现了Serializable)
- oos.writeBoolean(true);//boolean-->Boolean(实现了Serializable)
- oos.writeChar('a');//char-->Char(实现了Serializable)
- oos.writeDouble(9.5);//double-->Double(实现了Serializable)
- oos.writeUTF("芝麻干");//String类型序列化
- oos.writeObject(new Dog("阿黄",3));
- oos.close();
- System.out.println("数据保存完毕(序列化形式)");
- }
- }
写入数据(序列化数据)后,会生成一个.dat文件。

- package com.io.inputSteam;
-
- import com.io.outputstream_.Dog;
-
- import java.io.FileInputStream;;
- import java.io.IOException;
- import java.io.ObjectInputStream;
-
- /**
- * @author 华子
- * ObjectInputStream实现数据反序列化
- */
- public class ObjInputStream {
- public static void main(String[] args) throws IOException, ClassNotFoundException {
- String filePath = "e:\\data.dat";
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
- // 读取(反序列化)的顺序要和你保存的数据(序列化)的顺序一直
- System.out.println(ois.readInt());
- System.out.println(ois.readBoolean());
- System.out.println(ois.readChar());
- System.out.println(ois.readDouble());
- System.out.println(ois.readUTF());
- // dog的编译类型是Object,运行类型是Dog
- Object dog = ois.readObject();
- System.out.println("运行类型:"+dog.getClass());
- System.out.println(dog);
- // 如果要引用Dog的方法,需要向下转型
- Dog dog1 = (Dog)dog;
- System.out.println(dog1.getName());
- ois.close();
- }
-
- }
读取数据(反序列化)
运行结果:

对象处理流有很多细节,在这里总结一下:
1)读写顺序要一致
2)要求实现序列化或反序列化对象,需要实现Serializable
3)序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
5)序列化对象时,要求里面属性的类型也需要实现序列化接口
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化