java io -- FileInputStream

接上篇文章java io -- InputStream,本文将剖析InputStream中最常用的一个子类FileInputStream

FileInputStream是对一个文件抽象而成的数据流,我们这里先展示一下这个类的结构。

图1 FileInputStream类


可以看到,这个结构和InputStream大致一致,不过多了一些特性。

首先这个类的构造函数,可以通过String或File进行构造一个FileInputStream对象,但是需要注意,如果路径错误,没有对应的文件,会抛出异常。


下面我们将从源码的角度,看几个重要的方法。

由于读取文件时,首先需要打开文件,因此多了open()方法,为了简化读取操作,又增加了几个构造方法。

private native void open0(String name) throws FileNotFoundException;

private void open(String name) throws FileNotFoundException {
    open0(name);
}

打开文件,最终用的都是open0()这个方法,这个方法是个native方法。

public int read() throws IOException {
    return read0();
}
private native int read0() throws IOException;

读取文件也最终时是一个native方法,不过请参考上一篇文章中,对InputStream的说明,这个read()也必然是一个block的方法,不过由于时间短,我们感受不到罢了。

这个read()方法的实现中,最终是利用文件句柄读取了文件内容,有兴趣的可以去看c++源码。


FileInputStream的使用示例:

我这里用一个简单的例子说明一下,这里用到了FileInputStream,代表我们从一个目录中读取文件中的内容。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by zhaohui on 16-10-15.
 */
public class InputRead {
    public static void main(String[] args) {
        try {
            InputStream in = new FileInputStream("/home/zhaohui/tmp/zhaohui");

            int length = 0;

            //------------     单字节读取   ----------------
            // 循环读取文件,每次读取一个字节,如果读到文件末尾,返回-1
            int b;
            for (;(b=in.read())>0;){
                length ++;
            }
            in.close();
            System.out.println("the length is " + length);

            // ----------    多字节读取   -------------------
            // 将文件中数据读满(如果足够)字节数组
            //length = 0;
            in = new FileInputStream("/home/zhaohui/tmp/zhaohui");
            byte[] array1 = new byte[100];
            length = in.read(array1);
            in.close();
            System.out.println("the length is " +length);

            // ------------   从流中读取的字节数太多   -----------
            byte[] array = new byte[1];
            in.read(array, 0, 3);
            in.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }
}


输出:

Exception in thread "main" java.lang.IndexOutOfBoundsException

at java.io.FileInputStream.readBytes(Native Method)

at java.io.FileInputStream.read(FileInputStream.java:255)

at InputRead.main(InputRead.java:36)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

the length is 10

the length is 10

 

上面的例子,说明了inputStream的两种用法,一次读取一个字节和直接读取多个字节,以及一个错误的示例,如果读取出的字节数太多,容纳数据的数组太小,就会抛出异常。


我的总结:

1)InputStream作为java.io包中一个top class,定义了众多的抽象方法,比如read(),作为template模式,也实现了读取多个字节的read方法。

2)FileInputStream作为InputStream的一个子类,不仅实现了read方法,并根据自身特点添加了特性。

由于InputStream有众多的子类,我们最常用的就是文件流,因此这里只对FileInputStream做了介绍,其他的请自行查阅官方文档。

下一篇文章将介绍一个特殊的InputStream子类,FilterInputStream。




  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值