按流的方向分类:
1. 输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。 2. 输出流:数据流向是程序到目的地(以OutPutStream、Writer结尾的流)。 
按处理的数据单元分类:
Stream 结尾的流一般是字节流,如FileInputStream、FileOutputStream。Reader/Writer 结尾的流一般是字符流,如FileReader、FileWriter。按处理对象不同分类:
FileInputStream、FileReader、DataInputStream等。BufferedInputStream、BufferedReader 等。处理流也叫包装流。
- 节点流处于IO操作的第一线,所有操作必须通过它们进行
- 处理流可以对节点流进行包装,提高性能或提高程序的灵活性

表示字节输入输出流的所有类的父类。
子类:
FileInputStream / FileOutputStream: 节点流,以字节为单位 【直接】操作『文件』ByteArrayInputStream / ByteArrayOutputStream:节点流,…操作『字节数组对象』ObjectInputStream / ObjectOutputStream:处理流,…『对象』DataInputStream / DataOutputStream:处理流,…『基本数据类型与字符串类型』表示用于读取/写入的字符流抽象类,数据单位为字符.
子类:
FileReader / FileWriter:节点流,以字符为单位直接操作『文本文件』(只能读写文本文件)BufferedReader / BufferedWriter:处理流,将Reader/Writer对象进行包装,增加缓存功能,提升读写效率BufferedInputStream / BufferedOutputStream:处理流,将InputStream/OutputStream对象包装,…InputStreamReader / OutputStreamWriter:处理流,将字节流对象转化为字符流对象PrintStream:处理流,将OutputStream进行包装,可以方便地输出字符fis = new FileInputStream("a.txt");while ((tmp = fis.read()) != -1) sb.append((char) tmp);...FileOutputStream fos = null;String string = "i am writing.";try { fos = new FileOutputStream("a.txt", true); // true表示追加文件末尾 byte[] bytes = string.getBytes(); fos.write(bytes); // 直接将字符数组写入文件字节流不能很好的处理Unicode字符,经常会出现“乱码”现象,一般使用字符流处理文本文件。
FileReader fr = null;FileWriter fw = null; try { fr = new FileReader("a.txt"); fw = new FileWriter("./c.txt"); char[] buffer = new char[1024]; // 缓存数组 int len = 0; while ((len = fr.read(buffer)) != -1) fw.write(buffer, 0, len); } catch (Exception e) {...Java缓冲流本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率,就像是把别的流包装起来一样,因此缓冲流是一种处理流(包装流)。
因为缓冲流是先将数据缓存起来,然后当缓存区存满后或者手动刷新时再一次性的读取到程序或写入目的地。
// 使用缓冲流实现文件的高效率复制FileInputStream fis = null;BufferedInputStream bis = null;FileOutputStream fos = null;BufferedOutputStream bos = null;String srcPath = "/home/cenjw/Downloads/ideaIU-2019.3.5.tar.gz";String destPath = "/home/cenjw/idea-package.tar.gz";try { fis = new FileInputStream(srcPath); fos = new FileOutputStream(destPath); bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); int t = 0; long start = System.currentTimeMillis(); while ((t = bis.read()) != -1) bos.write(t); long end = System.currentTimeMillis(); System.out.println(end - start);FileReader fr = null;BufferedReader br = null;FileWriter fw = null;BufferedWriter bw = null;try { fr = new FileReader("a.txt"); fw = new FileWriter("./d.txt"); br = new BufferedReader(fr); bw = new BufferedWriter(fw); String tmpStr = ""; while ((tmpStr = br.readLine()) != null) { bw.write(tmpStr); bw.newLine(); }readLine()方法是BufferedReader特有的方法,可以对文本文件进行更加方便的读取操作。
写入一行后要记得使用newLine()方法换行。
ByteArrayInputStream和ByteArrayOutputStream经常用在需要流和数组之间转化的情况!
即,FileInputStream是把文件当做数据源。ByteArrayInputStream则是把内存中的”某个字节数组对象”当做数据源。
// 字符串转变为字节数组byte[] bytes = "hello world".getBytes();ByteArrayInputStream bais = null;StringBuilder sb = new StringBuilder();try { int tmp = 0; int cnt = 0; bais = new ByteArrayInputStream(bytes); while ((tmp = bais.read()) != -1) { sb.append((char) tmp); cnt++; }数据流将**“基本数据类型与字符串类型”作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型。
DataInputStream 和DataOutputStream 是处理流,可以对其他节点流或处理流进行包装,增加一些更灵活、更高效的功能。
InputStreamReader/OutputStreamWriter 用来实现将字节流转化成字符流。
System.in 是字节流对象,代表键盘的输入,按行接收用户的输入时,必须用到缓冲字符流 BufferedReader 特有的方法readLine(),但在创建BufferedReader的构造方法的参数必须是一个Reader对象,因此需要用到转换流InputStreamReader。
System.out 也是字节流对象,代表输出到显示器,按行读取用户的输入后,并且要将读取的一行字符串直接显示到控制台,就需要用到字符流的 write(String str) 方法,所以我们要使用OutputStreamWriter将字节流转化为字符流。
// 创建字符输入输出流BufferedReader br = null;BufferedWriter bw = null;try { // 使用转换流将 字节流转为字符流 br = new BufferedReader(new InputStreamReader(System.in)); bw = new BufferedWriter(new OutputStreamWriter(System.out)); String str = br.readLine(); while (! "exit".equals(str)) { bw.write(str); bw.newLine(); bw.flush(); str = br.readLine(); } ...把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。
对象序列化的作用:
ObjectOutputStream 代表对象输出流,它的 writeObject(Object obj) 方法可对参数指定的 obj 对象进行序列化,把得到的字节序列写到一个目标输出流中。ObjectInputStream 代表对象输入流,它的readObject() 方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了
Serializable接口的类的对象才能被序列化。 Serializable接口是一个空接口,只起到标记作用。
FileOutputStream fos = null;ObjectOutputStream oos = null;ObjectInputStream ois = null;FileInputStream fis = null;try { Person person = new Person(22, true, "jayvee"); // 通过ObjectOutputStream将Person对象的数据写入到文件,即序列化 fos = new FileOutputStream("a.txt"); oos = new ObjectOutputStream(fos); oos.writeObject(person); oos.flush(); // 反序列化 fis = new FileInputStream("a.txt"); ois = new ObjectInputStream(fis); Person p = (Person) ois.readObject(); System.out.println(p);...// 实现Serializable接口后,Person对象才能被序列化class Person implements Serializable { // 添加序列化ID,它决定着是否能够成功反序列化! private static final long serialVersionUID = 1L;
笔记参考:https://www.sxt.cn/Java_jQuery_in_action/ten-javaio-streamclass.html
IO流体系图:https://blog.csdn.net/u010145219/article/details/89792877
本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/15940811.html