近段时间,对apache commons io的源码做了深入的了解,在此把一些见解与大家分享。
首先我选择了大部分框架还依赖的2.2版本而不是最新的2.4版本(2.5发行版还没有发布)进行源码的研读,今天就简介一下commons io的input部分。
Input部分并不复杂,只是功能较多,主要由以下十一部分组成:通用部分、反向行读取功能、文件变更监听器、异常输入流标记、字节序相关功能、计数器相关功能、关闭输入流相关功能、三通相关功能、BOM相关功能、序列化相关功能、流间对接相关功能、测试流相关功能、线程绑定部分。
但我们应该先来了解一下Input所依赖的以下commons-io类:
org.apache.commons.io.FileUtils
文件工具类,该类只使用了它的判断文件新旧功能。
有写文件、读文件、创建文件夹、复制文件/文件夹、删除文件/文件夹、从URL中获取文件、遍历后显示文件集结果、比较文件内容、修改文件最后修改时间、检查文件正确性,这些功能。
org.apache.commons.io.ByteOrderMark
字节顺序标记
为了识别 Unicode 文件,Microsoft 建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE(U+FFFE)字符开头。这作为一个“特征符”或“字节顺序标记(byte-order mark,BOM)”来识别文件中使用的编码和字节顺序。
org.apache.commons.io.EndianUtils
不同CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序。
最常见的有两种:
Little-endian:将低序字节存储在起始地址(小端字节序)
Big-endian:将高序字节存储在起始地址(大端字节序)
基于不同CPU字节序的不同,每个整形在各个系统的字节序就不同了。因此在转换的时候基于整形数进行位移操作就可以自适应系统的高低位字节序。
commons.io还提供了临时文件的功能,即那些临时上传一小段时间处理完业务后即删除的文件。
org.apache.commons.io.TaggedIOException
可添加标记的IO异常。可以通过标记来确认是哪一个输入输出流引起的。
通用部分:
org.apache.commons.io.input.ProxyInputStream
代理字节输入流
该类是一个超类,使用代理模式代理了一个FilterInputStream类,主要提供了beforeRead()前置增强、afterRead()后置增强、handleIOException()异常处理增强。由于该类是抽象类,因此各增强没有具体实现。
org.apache.commons.io.input.ProxyReader
代理字符输入流
该类是一个超类,使用代理模式代理了一个FilterReader类,主要提供了beforeRead()前置增强、afterRead()后置增强、handleIOException()异常处理增强。由于该类是抽象类,因此各增强没有具体实现。
反向行读取功能:
org.apache.commons.io.input.ReversedLinesFileReader
反向行文件字符输入流
该类对一个文件从最后一行开始进行逐行读取,以方便读取那些会将新数据写在最后的文件,例如日志文件。在创建实例对象时可进行字符集编码的设置。
文件变更监听器:
该文件变更监听器与Monitor部分文件变更监听的最大区别在于,该文件变更监听是通过末端行内容来判断,并读取变更后的新行。而Monitor部分文件变更则只通过文件最后修改时间来判断是否变更。
org.apache.commons.io.input.TailerListener
末端监听器
该接口以及Tailer、TailerListenerAdapter一起实现了监听文件内容是否变更的功能,TailerListener作为接口定义了监听的行为包括init初始化、fileNotFound文件不存在、fileRotated文件内容变更、handle(String)以行为读取单位处理文件内容变更、handle(Exception)当出现异常时的处理方法。
org.apache.commons.io.input.TailerListenerAdapter
末端监听器适配器
该类是TailerListener的实现类,个人认为其应该作为抽象类,但其并没有加abstract关键字,而TailerListener的各方法体也并未做处理。
org.apache.commons.io.input.Tailer
末端
该类通过代理TailerListener来实现监听指定文件内容变化的功能,主要是通过文件长度来判断文件是否变化,如果文件变化则会调用所代理的TailerListener的实现类的fileRotated进行响应处理。
异常输入流标记:
org.apache.commons.io.input.TaggedInputStream
该类使用TaggedIOException异常进行输入流的异常标记,通过isCauseOf()就可以判断出异常的抛出是否是由于该输入流引起的。
字节序相关功能:
org.apache.commons.io.input.SwappedDataInputStream
该类根据CPU的字节序类型进行自动转换,并且自动从输入流读取的数据封装为指定的基本数据类型。
计数器相关功能:
org.apache.commons.io.input.CountingInputStream
该类在读取字节时进行计数,可统计所读取字节的数量。
关闭输入流相关功能:
org.apache.commons.io.input.AutoCloseInputStream
该类在调用完read()进行流读取之后会自动关闭输入流,其关闭的方法与传统输入流的close()不同,而是采用实例化一个CloseInputStream代替原输入流的方式进行关闭。因此其关闭行为并不会真正的关闭流。
org.apache.commons.io.input.CloseShieldInputStream
该类重写了close方法,当用户close时替换代理类为CloseInputStream。这样做可以避免close掉原输入流,因此叫关闭防御输入流。
org.apache.commons.io.input.CloseInputStream
该类用于那些不方便关闭却又不希望该输入流在部分代码中被使用的情况,调用该类的read方法永远都返回-1。
其中org.apache.commons.io.output.ByteArrayOutputStream在发现没有内容需要输出时会将代理的InputStream赋值为CloseInputStream。
三通相关功能:
org.apache.commons.io.input.TeeInputStream
该类实现了一入两出的三通字节输入流,由调用处作为其中一个输出、代理的outputStream作为第二个输出,从而实现三通。
BOM相关功能:
org.apache.commons.io.input.BOMInputStream
这个输入流会对所代理输入流的字节顺序标记做处理,它首先判断并获取这个字节顺序标记,记录它的长度以及其所对应的字节编码等,然后在read时可以采取自动跳过处理。
org.apache.commons.io.input.XmlStreamReader
该类实现了从一个URL或字节输入流读取字符的功能,并可猜测其字符集编码,但不一定是正确的。
其中org.apache.commons.io.output.XmlStreamWriter使用了XmlStreamReader中判断是否为xml内容的正则表达式。
org.apache.commons.io.input.XmlStreamReaderException
该类由XmlStreamReader在字符集编码不能确定时抛出。
序列化相关功能:
org.apache.commons.io.input.ClassLoaderObjectInputStream
该类用于序列化输入流,当对象序列化后可以字节流的形式在输入输出流中传递,ObjectInputStream可将输入流中的对象字节流还原为对象,而该类则可以获取这些类的类型以及代理类型。
流间对接相关功能:
org.apache.commons.io.input.ReaderInputStream
该类同时代理了一个Reader和一个InputStream,并从Reader中读取字符流根据指定的字符集编码输出为字节流。
org.apache.commons.io.input.CharSequenceInputStream
该类将输入流按照指定的字符集编码进行读取转换,对String、StringBuffer等作为输入流时可一个字节一个字节地读取。
org.apache.commons.io.input.CharSequenceReader
该类可直接读取String、StringBuffer等CharSequence的子实现类,读取后变为字符数组。
测试流相关功能:
org.apache.commons.io.input.BrokenInputStream
该类在重载InputSream的各个方法时都进行抛出IOException的处理,并且为了更准确地提供错误信息,可以在实例化对象时传IOException的子类对象作为异常抛出的对象。该类主要用于出错时的异常处理。
org.apache.commons.io.input.NullInputStream
该类是测试时使用的桩输入流类。例如测试时输入流数据量比较大则可使用该类进行测试,该类提供了一个processBytes()方法来提供测试的字节数据,在使用时需要重写该方法。
org.apache.commons.io.input.NullReader
该类是测试时使用的桩阅读器类。例如测试时阅读器数据量比较大则可使用该类进行测试,该类提供了一个processBytes()方法来提供测试的字节数据,在使用时需要重写该方法。
线程绑定部分:
org.apache.commons.io.input.DemuxInputStream
该类会将所代理的输入流绑定到当前线程上,只要是基于当前线程以及其子线程的都可以同步访问该输入流。其实现是通过ThreadLocal进行实现的。
ONE FOR IT是一个呆萌CTO打理的资讯读物,每天只为你准备一篇IT行业新鲜资讯。互联网的前沿,一篇就够了。(ID:OFI)