读写操作在Android底层的调用顺序

作者:Aningsk ,本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

 

参考了http://blog.chinaunix.net/uid-26926660-id-3326678.html

在Android中读写文件的类主要有FileReader/FileWriter,FileInputStream/FileOutputStream,RandomFileAccess。其中FileReader/FileWriter主要是用于以字符为单位的读写操作;FileInputStream/FileOutputStream主要是用于以字节为单位的读写操作;RandomFileAccess是一个独立的读写类,偏向于文件的随机读写。

下面主要以read为例来说明Android的读写顺序,write操作的调用与read类似。

如上图是这三个类的关系图。FileReader继承于InputStreamReader,InputStreamReader继承于抽象类Reader。FileInputStream继承于抽象类InputStream。RandomFileAccess没有继承什么特别的读写类。(黄色框表示抽象类,红色箭头代表调用关系)

 

在FileReader.java(安卓源码目录 /libcore/luni/src/main/java/java/io/ FileReader.java,上图中的类除了IoBridge.java都在这个目录)中可以看到,里面并没有read/write方法,所以它是使用它的父类InputStream类的read/write方法。

FileReader的构造方法是调用父类的构造方法(见下图),参数是FileInputStream类的匿名实例。

InputStreamReader的构造方法(下图)中使用了属于InputStream类的in实例,并在之后的read方法中使用in的read方法。也就是说使用FileReader类进行read操作,将最终调用到FileInputStream的read方法。这个in就是上图中的new FileInputStream(file)。

在FileInputStream.java可以看到read方法的定义,将去调用IoBridge的read方法(RandomFileAccess类中也是去调用IoBridge.read):

接下来的调用如下图所示:

在IoBridge.java(安卓源码目录/ libcore/luni/src/main/java/libcore/io/IoBridge.java),可以看到它的read方法中如下(那句File.Log是我自己加的):

将去调用Libcore.os.read。在同目录下的Libcore.java内容很简单:

它用BlockGuardOscar定义了一个Os实例,在BlockGuardOscar.java中做的事情并不是很多,里面的方法基本都会return os.XXX去调用os的方法后返回。在这里os是Posix的实例。在同目录的Posix.java中定义了大量JNI接口函数。我理解这个文件的作用就是,为Java的程序提供Posix协议中函数的接口,Linux就是符合这个协议的。

从上图可以看到read将会调用本地方法readBytes(),在Posix.java对应的JNI文件(libcore_io_Posix.cpp)中我们可以找到这个函数的具体实现。

文件libcore_io_Posix.cpp(安卓源码目录/ libcore/luni/src/main/java/native/ )实现了Posix_readBytes函数:

其中的throwIfMinusOne函数:

可以看出将执行TEMP_FAILURE_RETRY(expression)。

TEMP_FAILURE_RETRY(expression)是GNU库函数宏。

这个宏的作用:在信号到来时,如果正在进行原始的IO操作,如read/write 函数正在发生;在Posix协议中,建议这些函数直接返回错误EINT。所以一般情况下,程序员使用库函数,需要检查返回值是否为EINT,并准备再次调用以完成刚刚失败的操作,如果忘记了可能会造成比较大的麻烦。

GNU提供了这个宏来解决这个问题。这个宏会执行expression,直到返回值不是EINT。这样就不必程序员对EINT有过多的考虑。

到这里就已经离开了Android核心库,调用到了Linux Kernel的read函数。可能描述的比较乱,其实看看上面的两个流程图就比较清晰了。

 

这是是我在APK中写的读写SD卡的部分代码:

写文件是由FileOutputStream.write完成的,读文件是有FileInputStream.read完成的。

打印的Log(添加Log的具体方法,请参见上篇博客):

 

Aningsk

2014-7-14

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值