概念

I/O是Input和Output的缩写,Java中的I/O指的是处理输入与产生输出的工具类。
I/O指的是内存与存储介质之间的数据交换,广义的存储介质包括磁盘、网络等。
流Stream:在Java中通常以流的方式来处理I/O,一个流指的是一个字节序列。
Java提供的输入输出流都在java.io包中。

分类

按照传输方向分为输入流和输出流
按照传输内容分为字节流和字符流
按照目的分为:

  • 文件读取:files
  • 网络:network
  • 内存中的缓存获取:in-memory buffers(arrays)
  • 线程中通信:pipes
  • 缓存:buffering
  • 过滤:filtering
  • 解析:parsing
  • 读写文本
  • 读写基本数据类型
  • 读写对象:
  • system.in、system.out、system.error

    输入输出流

    在Java API中,可以从其中读取一个字节序列的对象称为输入流,而可以向其中写入一个字节序列的对象称为输出流。这些字节序列的来源地和目的地可以是文件(通常都是文件),也可以是网络连接,甚至是内存块。抽象类InputStream和OutputStream构成了输入/输出类层次结构的基础。
    因为面向字节的流不便于处理以Unicode形式存储的信息,所以从抽象类Reader和Writer中继承出来了一个专门用于处理Unicode字符的单独的类层次结构。这些类拥有的读入和写出操作都是基于两字节的Char值而不是基于byte值的。
    输入流InputStream:Java程序使用输入流从数据源读取数据,数据源可以是文件、数组、外部设备、socket。
    输出流OutputStream:java程序使用输出流将数据写入到目的地,目的地可以是文件、数组、外部设备、socket。
    从输入流到输出流的整个过程如下图所示:
    01-I/O - 图1

InputStream

字节输入流用于从流中读取单个字节或字节数组。
字节输入流有以下实现子类:

FileInputStream

从文件中创建字节输入流

ByteArrayInputStream

从字节数组创建字节输入流

FilterInputStream

过滤流,用于向处理字节的输入流添加额外的功能

DataInputStream

支持以二进制的方式读取所有的Java基本类型

BufferedInputStream

通过内部字节数组给一个输入流增加缓冲功能

PushBackInputStream

支持从字节输入流中预读取一个字节,可以回推到流中

PipedInputStream

可以和PipedOutputStream连接,连接口可以读取PipedOutputStream写入的字节

ObjectInputStream

SequenceInputStream

接收多个输入流,对其进行concat,形成一个新的输入流


字节输出流

这个抽象类是所有表示字节输出流的类的超类。
子类实现这个抽象类的时候必须实现write()抽象方法,写入一个字节到输出流中。

  1. public abstract class OutputStream implements Closeable, Flushable {
  2. // 将特定的字节b写入到输出流,忽略b的高24位,将低8位写入输出流。
  3. public abstract void write(int b) throws IOException;
  4. // 将指定字节数组写入到输出流,与write(b, 0, b.len)具有相同的效果。
  5. public void write(byte b[]) throws IOException {};
  6. // 将指定字节数组b从off偏移开始的最多len个字节写入到输出流。
  7. public void write(byte b[], int off, int len) throws IOException {};
  8. public void flush() throws IOException {};// 刷新此输出流,强制将缓存的输出字节写出。
  9. public void close() throws IOException {};// 关闭输出流,释放系统资源。
  10. }

OutputStream的继承层次
01-I/O - 图2

IO.xmind

字符流

字符输入流 Reader

  1. // 用于读取字符流的抽象类
  2. public abstract class Reader implements Readable, Closeable {
  3. protected Object lock;
  4. protected Reader() {
  5. this.lock = this;
  6. }
  7. protected Reader(Object lock) {
  8. if (lock == null) {
  9. throw new NullPointerException();
  10. }
  11. this.lock = lock;
  12. }
  13. public int read(java.nio.CharBuffer target) throws IOException {}
  14. public int read() throws IOException {}
  15. public int read(char cbuf[]) throws IOException {}
  16. // 从输入流读取指定长度的字符到字符数组,子类必须实现该方法
  17. abstract public int read(char cbuf[], int off, int len) throws IOException;
  18. // 跳过指定长度的字符
  19. public long skip(long n) throws IOException {};
  20. // 流是否准备好被读取
  21. public boolean ready() throws IOException {};
  22. // 流是否支持mark()操作
  23. public boolean markSupported() {};
  24. // 标记流的当前位置
  25. public void mark(int readAheadLimit) throws IOException {};
  26. // 重置流。如果流已被标记,则尝试将其重新定位在标记处。如果流尚未被标记,则尝试以某种方式重置,比如将其重新定位到起点。
  27. // 并未所有字符输入流都支持reset操作,还有些支持reset但是不支持mark操作。
  28. public void reset() throws IOException {};
  29. // 关闭流,释放相关的系统资源,子类必须实现该方法。
  30. abstract public void close() throws IOException;
  31. }

字符输入流Reader的继承层次:
01-I/O - 图3

字符输出流 Writer

  1. // 用于写入字符流的抽象类
  2. public abstract class Writer implements Appendable, Closeable, Flushable {
  3. private char[] writeBuffer;// 用于保存字符串和单个字符写入的临时缓冲区
  4. private static final int WRITE_BUFFER_SIZE = 1024;// writeBuffer 的大小,必须 >= 1
  5. // 用于同步此流上的操作的对象。为了提高效率,字符流对象可以使用除自身之外的对象来保护临界区。因此,子类应该使用此字段中的对象而不是 this 或同步方法。
  6. protected Object lock;
  7. // 创建一个新的字符流编写器,其临界区将在编写器本身上同步。
  8. protected Writer() {
  9. this.lock = this;
  10. }
  11. // 创建一个新的字符流编写器,其临界区将在给定对象上同步。
  12. protected Writer(Object lock) {
  13. if (lock == null) {
  14. throw new NullPointerException();
  15. }
  16. this.lock = lock;
  17. }
  18. // 写入单个字符。要写入的字符包含在给定整数值的低16位中;高16位被忽略。实际调用write(writeBuffer, 0, 1);
  19. public void write(int c) throws IOException {}
  20. // 写入字符数组,实际调用write(cbuf, 0, cbuf.length)
  21. public void write(char cbuf[]) throws IOException {}
  22. // 写入字符数组从偏移位置off开始长度为len的部分。子类必须实现该方法。
  23. abstract public void write(char cbuf[], int off, int len) throws IOException;
  24. // 写入字符串,实际调用write(str, 0, str.length());
  25. public void write(String str) throws IOException {}
  26. // 写入字符串的子串
  27. public void write(String str, int off, int len) throws IOException {};
  28. // 将指定的字符序列附加到此编写器。
  29. public Writer append(CharSequence csq) throws IOException {};
  30. public Writer append(CharSequence csq, int start, int end) throws IOException {};
  31. public Writer append(char c) throws IOException {};
  32. abstract public void flush() throws IOException;
  33. abstract public void close() throws IOException;
  34. }

字符输出流的继承层次:
01-I/O - 图4

字节流和字符流的转换

InputStreamReader:将字节输入流 转换成 字符输入流

  1. // 字节流到字符流的桥梁。读取字节,编码成为字符。内部方法调用的都是StringDecoder的方法。
  2. public class InputStreamReader extends Reader {
  3. private final StringDecoder sd;
  4. // 基于 字节输入流 和 字符集 创建 字符输入流
  5. public InputStreamReader(InputStream in) // 基于默认字符集的构造函数
  6. public InputStreamReader(InputStream in, String charsetName) //基于指定名称字符集的构造函数
  7. public InputStreamReader(InputStream in, Charset cs) //基于指定字符集的构造函数
  8. public InputStreamReader(InputStream in, CharsetDecoder dec) {} //
  9. public String getEncoding() {}
  10. public int read() throws IOException {} // 读取单个字节
  11. public int read(char cbuf[], int offset, int length) throws IOException {} // 读取字节数组
  12. public boolean ready() throws IOException {}
  13. public void close() throws IOException {}
  14. }
  15. public class StreamDecoder extends Reader {}

OutputStreamWriter:将字节输出流 转换成 字符输出流

  1. public class OutputStreamWriter extends Writer {
  2. private final StreamEncoder se;
  3. // 基于 字节输出流 和 字符集 创建 字符输出流
  4. public OutputStreamWriter(OutputStream out) {}
  5. public OutputStreamWriter(OutputStream out, String charsetName) {}
  6. public OutputStreamWriter(OutputStream out, Charset cs) {}
  7. public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {}
  8. public String getEncoding() {}
  9. void flushBuffer() throws IOException {}
  10. public void write(int c) throws IOException {} // 写入字符
  11. public void write(char cbuf[], int off, int len) throws IOException {} // 写入字符数组
  12. public void write(String str, int off, int len) throws IOException {} // 写入字符串
  13. public void flush() throws IOException {}
  14. public void close() throws IOException {}
  15. }
  16. public class StreamEncoder extends Writer {}

节点流

缓冲区

  1. public class ByteArrayInputStream extends InputStream{} // 字节数组输入流
  2. public class ByteArrayOutputStream extends OutputStream{} // 字节数组输出流
  3. public class CharArrayReader extends Reader{} // 字符数组输入流
  4. public class CharArrayWriter extends Writer{} // 字符数组输出流

文件

  1. public class FileInputStream extends InputStream{}
  2. public class FileOutputStream extends OutputStream{}
  3. public class FileReader extends InputStreamReader{}
  4. public class FileWriter extends OutputStreamWriter{}

管道

管道用于线程间的通信

  1. public class PipedInputStream extends InputStream{}
  2. public class PipedOutputStream extends OutputStream{}

系统输入输出

Java中存在三个系统标准流,他们在JVM启动时就会自动实例化。

  1. public final class System {
  2. public final static InputStream in = null;
  3. public final static PrintStream out = null;
  4. public final static PrintStream err = null;
  5. }

System.in:将键盘作为输入的标准输入流
System.out:将控制台作为输出的标打印出流
System.err:将控制台作为输出的错误打印流

处理流

处理流:接收一个流作为参数,进行一些处理。

过滤流

过滤流接收输入输出流,进行数据的转换或者提供附加功能。

  1. public class FilterInputStream extends InputStream{}
  2. public class FilterOutputStream extends OutputStream{}
  3. public class FilterReader extends Reader{}
  4. public class FilterWriter extends Writer{}

缓冲流

缓冲流接收一个输入流或输出流。

  1. public class BufferedInputStream extends FilterInputStream{}
  2. public class BufferedOutputStream extends FilterOutputStream{}

打印流

打印流是输出流,包括字节输出流和字符输出流。

  1. public class PrintStream extends FilterOutputStream{}
  2. public class PrintWriter extends FilterWriter{}

Sequence流

Sequence输入流可以接收多个输入流,并将它们的内容写入到新的输入流中去。

  1. public class SequenceInputStream extends InputStream{
  2. SequenceInputStream(InputStream s1, InputStream s2)
  3. }