一堆废话(赶快跳过)
在我们的日常开发中 I/O
涉及到我们开发的方方面面,虽然早在 JDK1.5
就新增了 NIO
的概念,但是 java.io
的使用以及技巧在我们的日常开发中还是占据很高的比重。
概念(不看也行)
最基本的I/O
流是 java.io
包中的抽象类 java.io.InputStream
和 java.io.OutputStream
。s有预留的设计比较早,因此并没有采用现在流行的面向接口的编程思路,而是采用了抽象类。新增的I\O
相关的API则大量使用了接口。如果留的实现只是对使用者暴漏字节这个层次的细节,则可以直接集成InputStream 或 OutputStream 类,并且提供自己二外的能力。
在接下来的几个章节中,会逐章记录
以下各种流类的详细使用方法
-
BufferedInputStream
,BufferedOutputStream
缓冲复用流 -
ByteArrayInputStream
,ByteArrayOutputStream
byte数组缓冲流 -
DataInputStream
,DataOutputStream
java原生数据流 -
ObjectInputStream
,ObjectOutputStream
对象序列化流 -
PushbackInputStream
,PushbackOutputStream
推回流 -
PipedInputStream
,PipedOutputStream
管道流 -
SequenceInputStream
,SequenceOutputStream
序列流
和字符流类和字符流的的装饰类
-
Reader
,Writer
-
InputStreamReader
,InputStreamWriter
-
StringReader
,StringWriter
-
BufferedReader
,BufferedWriter
-
CharArrayReader
,CharArrayWriter
同时也会记录一些 java8 融入 Google guava
类库对 流类的支持。
基本输入流
输入流 InputStream
类中包含两类功能
输入流的两大功能
- 读取流中字节数据的功能是通过 read 方法来完成。该方法有以下3种重载形式
public abstract int read() throws IOException
public int read(byte b[]) throws IOException
public int read(byte b[], int off, int len) throws IOException
比较常见的操作流的方式就是 创建一个字节数组作为缓冲区,然后循环读取,直到read方法返回-1或抛出 java.io.IOException 异常。read方法的返回值是每次调用中成功读取的字节数。
需要要注意的是在读取的过程中,对read方法调用是阻塞的。当流中没有数据可用时,对read方法的调用需要等待。这种阻塞式的特性可能会成为应用中的性能瓶颈。
如果不使用字节数组,那么read方法每次只能读取到一个字节,再有缓冲区的情况下虽然InputStream类每次也只是读取一个字节,但是 InputStream类的子类一般会接受一个缓冲区最为参数的read方法提供更高效的实现。
抽象
正像他的名字一样,字节流是流动的,像流水一样。刘中的字节一旦流过去,就无法重新使用。
-
控制流的功能。
-
close
关闭功能
通过 close 方法,我们可以关闭一个 流,就像拧上水管龙头一样。java7及以后,更推荐使用try-with-resource
语句来使用流。可以避免显示的调用close方法。
java
try ( FileInputStream fInput = new FileInputStream(new File("path/to/exists_file")); FileOutputStream fOutput = new FileOutputStream(new File("path/to/new_file")); ) { // ....fInput -> read -> fOutput } catch (IOException e) { ..... } catch (FileNotFoundException e) { ..... }
skip
跳过若干个字节。相当于保留当前的位置往后移动若干个字节,这个功能可以通过skip方法来实现并不是所有的InputStream累都支持skip方法。mark
读取位置标记-
reset
读取位置重置
标记和重置是配合使用的,可以实现可以实现流中的内容重复读取,而不会像一般的读取那样操作,数据流过去之后就无法在次读取。但是并不是所有的流都支持标记功能,因此在使用mark方法来标记当前位置之前,需要通过markSupporetd方法来判断当前流的实现是否支持标记功能。 -
available
获取当没有阻塞情况下,当前流中还有多少字节可供读取。如果我们每次读取调用available方法获取到的字节书,不如在读取一个大文件的同时对文件的内容进行处理,如果每次读取是都不发生阻塞,就可以比较好的平均数据读取和处理的时间。
-
基本输出流
与InputStream类相对应的OutputStream类表示基本的输出流,用来把数据从程序输出到其他地方。基本OutputStream类的对象也是在自己这个层次上操作。其中最主要的是写入数据的write方法。
-
write 写入方法。
public abstract void write(int b) throws IOException
public void write(byte b[]) throws IOException
public void write(byte b[], int off, int len) throws IOException
write 方法也有3种类似的重载形式,可以每次写入一个字节,也可以写入一个字节数组中全部或部分内容。
-
控制方法
-
close
方法
关闭当前输出流 -
flush
方法
强制要求OutputStream类对象对暂时保持内部缓冲区中的内容立即进行实际的写入操作。因为有些OutputStream类的子类会在内部维护一个缓冲区,通过write方法写入的数据会被首先放在这个缓冲区中,然后再摸个适合的实际执行已经缓冲的内容的写入操作。在一般的场景中OutputStream对象的使用者一般不需要直接调用flush方法保证内部缓冲区数据成功写入。这是因为当OutputStream类对象内部的缓冲区满了以后,会自动执行写入操作。OutputStram类的对象被关闭时,flush方法一般也会被自动调用。
-