学了这么长时间的Java,发现对其IO的操作还是不熟悉,特地记录一下,以备日后复习。就从FileInputStream
开始吧,今天只简单的介绍其读取方法,这个方法看似简单,里面还是有很多知识点值得去挖一下的。
read方法一共有三种重载方式
- int read()
- int read(byte b[])
- int read(byte b[], int off, int len)
这三种重载方式都符合一下两条结论:
- read方法每读一次就会使文件指针向后移动一个字节或者N个字节(N=读取到的数组字节数<=指定的字节数组长度)
- 如果文件指针到文件末尾,就返回-1
首先验证验证上面两条结论
public class Test05 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("test.txt");
fos.write("hello".getBytes()); //向文件中写入5个字节(英文一个字母,包含英文的特殊字符都是只占一个字节)
fos.close();
FileInputStream fis = new FileInputStream("test.txt");
int b = fis.read(); //①
System.out.println("read = " + b);
int readLen = fis.read(new byte[5]); //②
System.out.println("read1 = " + readLen);
int readLen2 = fis.read(new byte[5], 0, 2); //③
System.out.println("read2 = " + readLen2);
}
}
①处返回的是读取到的字节值,只读取了1个字节
②处想要把5个字节全部读取出来,但却之读取到了4个字节,因为经过①处的代码,文件指针向后移动了一个字节,所以只剩下了4个字节
③处还想读取5个字节,不好意思,这时文件指针已经移动到了最后,没有字节可供你读取了,所以就直接返回-1
(调整三处代码的顺序以及指定的字节数组大小,可以更好的理解)
下面三个函数的结论首先包含上面两个结论
read()
这个很简单,结论就是
- 返回读到的字节值
read(byte b[])
int readLen = fis.read(new byte[10]);
System.out.println("readLen = " + readLen);
可以看到,我们指定了一个长度为10的字节数组,但是读取到字节长度只有5个,得出结论:
- 返回的就是读取到的数据字节文件长度,与给定的byte数组长度无关
int read(byte b[], int off, int len)
这个重载函数只是在上面的基础上,添加了两个参数
第一个off:就是offset,指的是在b中的起始位置
第二个len:从off开始向后的长度
int readLen = fis.read(new byte[5], 2, 3);
System.out.println("readLen = " + readLen);
结论是:
- 返回给定的len的长度
正常用法,这个方法有以下两个注意点:
- off<=b.len-1
- len<=b.len-off
不正常用法,就是这个方法有个BUG
首先看一下源码中关于off
的描述
注意,源码已经明确说明了,off是在b数组中的起始位置
int read2 = fis.read(new byte[5], 5, 0); //按理来说,off<b.len,但是它这样依然不报错
System.out.println("read2 = " + read2);
只不过返回值为0而已。
记住正确用法吧,先。找了半天更底层的源码也没找到原因。
看看下面的代码的执行结果的差别,想想为什么?
第一个
int len = 0;
byte[] bytes = new byte[4];
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes, 0, len)); //读取到的字节长度
}
结果
第二个
int len = 0;
byte[] bytes = new byte[4];
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes, 0, bytes.length)); //指定的字节数组长度
}
结果