Java 的 I/O 操作类可以分成四组:
- 基于字节操作的 I/O 接口:InputStream 和 OutputStream
- 基于字符操作的 I/O 接口:Writer 和 Reader
- 基于磁盘操作的 I/O 接口:File
- 基于网络操作的 I/O 接口:Socket
前两组根据数据格式,后两组根据传输方式。除了 Socket 类都在在 java.io
包下。
1 读写字节
抽象类InputStream
和OutputStream
构成了基于字节的 I/O 操作接口的基础。
一般使用InputStream
和OutputStream
的子类来读写数字、字符串和对象,而不是直接使用字节。子类复写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 流类的家族中,除了基于字节的InputStream
和OutputStream
和基于字符的Writer
和Reader
,还有4个附加接口:Closeable
、Flushable
、Readable
和Appendable
2.1 Closeable
Closeable
有close()
方法
java.io.Closeable接口扩展了java.lang.AutoCloseable接口。因此,对任何Closeable进行操作时,都可以使用try-with-resource 语句。
InputStream
、OutputStream
、Reader
和Writer
都实现了closeable
接口。
2.2 Flushable
Flushable
有flush()
方法
OutputStream
和Writer
实现了Flushable
接口。
2.3 Readable
Readable
有read(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 虚拟机将字节转换得到的,这个过程非常耗时,并且不知道编码类型就很容易出现乱码问题。
如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。