java源码之 io 流源码解读(三)
前面两篇已经基本介绍了基本输入流和包装输入流。 因此接下来的路要好走的多。 因为它们都是对称的,输入流的很多的读方法对应的是相应的写方法。还有就是发现自己原来的一个误区,就是flushable并不针对输入流开放,输入流中的与这个方法类似的为fill() 方法。
嗯还是按照时间线来记录:
就基本输出流而言:
第一个开刀的还是 FileOutputStream。 自然还是看他的核心方法。看图:
注意这里它们能够直接写入是因为这个流在实例化的时候已经与文件系统进行了交互:
另一点就是它提供了两种写入的方式,并且是不经java包装直接写入的,至于之后有没有包装不太清楚。 并且注意到两种写入方式都会带有一个是否追加(append)的标志位。 核心的方法看了之后好像没啥关心的了 哈哈哈,那就下一个吧。
下一个为FilterOutputStream,这个跟输入流是一样的,也是将核心方法给托管了。 但是这里终于可以处理那个flush了。 请看图:
可以看到,flush方法的本质就是调用了write方法。
关于dataOutputStream有一些额外的收获就是,比如写入一个int型数据,一个int型数据是占了4个byte,如何以一个一个的byte写入的呢?这里原来就是运用到了移位操作,直接上图具有说服力:
第一个为写入long型数据的方法,为8个byte,它是这样处理的,每次存的时候都进行了移位,我觉得有点像tcp的那个滑动窗口。 第二个写入的char型数据,移位后还进行了一个与操作,这也与之前读方法的那个与运算相呼应。 所谓负负得正嘛。
还有不知道大家是否听说过utf8编码,之前也看过相关的资料,utf8是采用的三个字节,24位进行字符的编码,能够表示世界各国的语言。 之前或许还有一丝怀疑,那么看了人家的注释之后大概就没有一丝怀疑了吧: 请看法宝:
因为屏幕不够大所以只能分两次截图。 但是更多的或许都不用说了。它就是这么真真实实的被运用于网络中。
又跑偏了,继续说输出流。
这里有一个特别特殊的输出流位于FilterOutputStream下面。它就是PrintStream。 进去查看它的方法发现了几个特别熟悉的方法,printLn(),print()。 这个怎么跟我们第一次写hello world那个那么像呢?? 于是点进去又有了发现:
世界就是如此奇妙,原来自己用了这么久的 System.out.println("hello world!")方法是这么来的。 真是因崔斯汀。至于更多的实现,则要等到自己以后有了时间与精力进一步钻研了。 同时需要知道的是PrintStream内部包含了这样一个依赖:
也就是说它是支持字符相关操作的。 有什么意义现在也说不清楚,但是感觉它很重要。 另外它的内部实现了多个方法的重构,这也是为什么我们即能输出字符串,又能输出二进制数,又能输出其他数据的原因。 并且它依赖于包装流:
至于ObjectOutputStream,当时只截了图:
更深的理解暂时没有。
下一个则是ByteArrayOutputstream。 同样来看它的核心方法:
可以知道它也是写在java内部的,这时感觉它变成了一个ArrayList呢,哈哈哈,为什么这么说呢? 请看:
有没有很熟悉嘿嘿嘿。 那么既然写入到的是内存中,那么如何读取它成了一个问题,看看源码:
这下应该明确了。 至此,基本输出流查看完毕。
包装输出流跟包装输入流惊人的相似,并且是对应的。就简单看看行了。
但是它的内部让我隐约仿佛看到了对象锁哈哈哈:
BufferedWriter没什么新鲜的就直接跳过。
StirngWriter内部跟StringReader有一点不一样。 上图:
同时它也是写在内存中的,如何读取呢?
最后剩下的就一个OutputStreamWriter和其子类FileOutputStreamWriter了。 它们依赖基本流跟InputStreamReader类似。就不介绍了。 只是这里它依赖的字符类处理的类变了,变为了Charset,CharsetEncoding。 即编码而非解码了。
最后的最后,终于把把他们记录完了,有一些之前想记的搞忘了,有一些之前没有想到的给记录下来了。 不管怎样吧,希望将来的自己能够感谢现在努力的自己。。。 也该去 happyhappy了,燥起来吧!~~~~