输入输出流

Wu Jun 2020-01-04 00:43:49
Categories: > > Tags:

Java 的 I/O 操作类可以分成四组:

  1. 基于字节操作的 I/O 接口:InputStream 和 OutputStream
  2. 基于字符操作的 I/O 接口:Writer 和 Reader
  3. 基于磁盘操作的 I/O 接口:File
  4. 基于网络操作的 I/O 接口:Socket

前两组根据数据格式,后两组根据传输方式。除了 Socket 类都在在 java.io 包下。

1 读写字节

抽象类InputStreamOutputStream构成了基于字节的 I/O 操作接口的基础。

一般使用InputStreamOutputStream的子类来读写数字、字符串和对象,而不是直接使用字节。子类复写read()、write()。

1.1 read()

阻塞。InpuStream 类抽象方法。读入一个字节,并返回读入的字节,或者在遇到输入源结尾时返回 -1。

1.2 write(int b)

阻塞。OutputStream 类抽象方法。向某个输出位置写出一个字节。

1.3 available()

非阻塞。InpuStream 类方法。检查当前可读入的字节数量。

int bytesAvailable = in.available();
if(bytesAvailable > 0){
    byte[] data = new byte[bytesAvailable];
    in.read(data);
}

1.4 close()

InpuStream、OutputStream 的 close() 方法释放系统资源

2 完整的流家族

Java 流类的家族中,除了基于字节的InputStreamOutputStream和基于字符的WriterReader,还有4个附加接口:CloseableFlushableReadableAppendable

2.1 Closeable

Closeableclose()方法

java.io.Closeable接口扩展了java.lang.AutoCloseable接口。因此,对任何Closeable进行操作时,都可以使用try-with-resource 语句。

InputStreamOutputStreamReaderWriter都实现了closeable接口。

2.2 Flushable

Flushableflush()方法

OutputStreamWriter实现了Flushable接口。

2.3 Readable

Readableread(CharBuffer cb)方法

CharBuffer 类拥有按顺序和随机地进行读写访问的方法,它表示一个内存中的缓冲区或者一个内存映像的文件

Reader实现了Readable

Appendable

Appendable接口有两个用于添加单个字符和字符序列的方法

Appendable append(char c)
Appendable append(CharSequence s)

CharSequence 接口描述了一个 char 值序列的基本属性,String、CharBuffer、StringBuilder 和 StringBuffer 都实现了它。

Writer实现了Appendable

3 组合输入、输出流过滤器

提示:所有在 java.io 中的类都将相对路径名解释为以用户工作目录开始,你可以通过调用 System.getProperty(“user.dir”) 来获得这个信息。

通过嵌套过滤器添加多重功能,灵活处理读写。

3.1 从文件中读入数字

FileInputStream fin = new FileInputStream("employee.dat");
DataInputStream din = new DataInputStream(fin);
double x = din.readDouble();

3.2 从文件中缓冲读取数据

DataInputStream din = new DataInputStream(
    new BufferedInputStream(
        new FileInputStream("employee.dat")));

3.3 预览下一个字节

PushbackInputStream pbin = new PushbackInputStream(
    new BuffererInputStream(
        new FileInputStream("employee.dat")));
int b = pbin.read();
if(b != '<') pbin.unread(b);

3.4 从 ZIP 压缩文件中读入数字

ZipInputStream zin = new ZipInputStream(FileInputStream("employee.zip"));
DataInputStream din = new DataInputStream(zin);

4 为什么要有字符流?

信息的最小存储单元都是字节,但 I/O 流提供了直接操作字符的接口,是因为字符流是由 Java 虚拟机将字节转换得到的,这个过程非常耗时,并且不知道编码类型就很容易出现乱码问题。

如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。