一.IO流基础概念
把数据从 数据源 输送到 数据目的地。
1.1:数据可能存在的位置
1.1.1:键盘输入(从控制台输入)
1.1.2:文件读入
1.1.2:java代码中
1.2:主要负责
输入和输出,相对于当前代码
1.3:输入输出方式:
1.3.1:字节---> 字节流
1.3.2:字符---> 字符流
1.4: 细分,都是位于 java.io 包里。
1.4.1:字节 输入流 : inputStream
1.4.2:字节 输出流 : outputStream
1.4.3:字符 输入流 : XxxxxReader
1.4.4:字符 输出流 : XxxxxxWriter
注: inputStream 和 outputStream 是抽象类
二.IO流 基础操作:
2.1:输入流 InputStream/Reader
2.1.1: read();会阻塞代码.从输入流读取一个字节(1字节是8位),把它转换为0-255之间的整数,并返回这一整数。如果遇到输入流的结尾,则返回-1;
2.1.2: read(byte[] but);会阻塞代码.从流中读取字节数据,把读取到的字节数据放到数组中,一直放满数组。返回的整数表示读取的字节数。如果遇到输入流的结尾,则返回-1;
2.1.3: read(byte[] b, int off, int len)会阻塞代码.从输入流读取若干个字节,把它们保存到参数b指定的字节数组中。返回的整数表示读取的字节数。参数off指定在字节数组中开始保存数据的起始下标,参数len指定读取的字节数目。返回的整数表示实现读取的字节数。如果遇到输入流的结尾,则返回-1;
注:第二个和第三个效率大于第一个。因为:减少进行物理读文件或键盘的次数,因此能提高I/O操作的效率。
2.1.4: available(): 返回可以从输入流中读取的字节数目;
2.1.5: skip(long): 从输入流中跳过参数n指定数目的字节/字符。
2.1.6: close(): 关闭输入流,不关闭流,资源被占用,其他进程不能使用
2.1.7: 字节流 读取到流尾 返回 -1;
2.1.8: 字符流 读取到流尾 返回 null;
以下是 不常用方法. 使用场景:从流中重复读入数据
2.1.7: boolean markSupported(): 返回true则表示这个流是否支持重复读入数据。
2.1.8: void mark(int):从流的当前位置开始设置标记,mark方法有个参数,通过这个整型参数,你告诉系统,希望在读出这么多个字符之前,这个mark保持有效。
2.1.9: void reset():该方法使输入流重新定位到刚才做了标记的起始位置。
mark祥解:
pos:读取的下一个位置。
markLimit: mark方法后reset方法前 最多允许读取的字节数,这个最大字节数,其实是由markLimit和buffer.size中较大的那个决定的。
当你调用mark方法时,内部会保存一个markPos标志,它的值为目前读取字节流的pos位置,倘若你调用reset方法,这时候会把pos重置为markPos的值,这样你就可以重读已经读过的字节.
eg:有一段字节流是helloworld, 当你读取完字母h调用mark方法(此时markPos指向字母e),接着你继续读取e,l,l,o 然后此时你调用reset方法(内部把pos重置为markPos),当你再读取下一个字节的时候,你会发现你读取到的是e而不是字母w,这样通过mark方法我们就是实现了重复读(re-read the same bytes)
2.2:输出流 OutputStream/writer
2.2.1: write(int b): 向输出流写入一个字节;
2.2.2: write(byte[] b): 把字节数组中的所有字节数据写到输出流;
2.2.3: write(byte[] b, int off, int len): 把字节数组中的字节从off位置开始的数据写len个长度到输出流.
2.2.4: flush(): flush()方法强制把缓冲区内的数据写到输出流中。
注:OutputStream类本身的flush()方法不执行任何操作,
但是,一些带有缓冲区的流,在write的时候,是先把数据保存到缓冲区,并不是把数据写到流中,所以需要flash把缓冲区中的数据刷到流中。
2.2.4: close(): 关闭输出流。