您好,登录后才能下订单哦!
这篇文章给大家分享的是有关JavaI/O之输入和输出的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
前言
编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。
在文章:<<Java I/O深入学习之File和RandomAccessFile>>中,我们讲到RandomAccessFile可以写入和读取文件,具备I/O功能,但是其只能针对文件,而I/O还涉及到很多其他场景比如网络、读取内存中的字符串等,所以Java类库中提供了一系列的类库来对其进行支持,也就是本文要总结学习的。
Java类库中的I/O类分成输入和输出两部分,可以在JDK文档里的类层次结构中查看到。通过继承,任何自Inputstream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或者字节数组。
但是,我们通常不会用到这些方法,它们之所以存在是因为别的类可以使用它们,以便提供更有用的接口。因此,我们很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所期望的功能(这是装饰器设计模式的应用,也有专门写文总结过:装饰器模式)。实际上,Java中“流”类库让人迷惑的主要原因就在于:创建单一的结果流,却需要创建多个对象。
I/O需要应对的场景往往是多样化的,Java类库的设计者则是通过创建大量的类来解决这个难题,区区一篇文章难以详述,本文也只是尽力对传统I/O类库所涉及到的类提供一个总览,在把握整个脉络的前提下才能更好的理解并应用I/O类库来解决实际编程问题。如需涉及到细节,还是需要参考JDK文档。
1. InputStream/OutputStream
Java 1.0中,类库的设计者首先限定与输入有关的所有类都应该从InputStream继承,而与输出有关的所有类都应该从OutputStream继承。
1.1 InputStream
InputStream的作用是用来表示那些从不同数据源产生输入的类。这些数据源包括:
字节数组;
String对象;
文件;
“管道”,工作方式与实际管道相似,即从一端输入,从另一端输出;
一个由其他种类的流组成的序列,以便我们可以将它们收集合并到一个流内;
其他数据源,如Internet连接等;
每一种数据源都有相应的InputStream子类,作为基础构件:
ByteArrayInputStream,允许将内存的缓冲区当作InputStream使用;
StringBufferInputStream,将String转换成InputStream;
FileInputStream,用于从文件中读取信息;
PipedInputStream,产生用于写入相关PipedOutputStream的数据。实现“管道化”概念;
SequenceInputStream,将两个或多个InputStream对象转换成单一InputStream;
1.2 OutputStream
OutputStream的作用是表示那些可以输出到不同数据源的类,其具体的子类决定了输出所要去往的目标:字节数组、文件或管道,同样是作为基础构件:
ByteArrayOutputStream,在内存中创建缓冲区。所有送往“流”的数据都要放置在此缓冲区;
FileOutputStream,用于将信息写至文件;
PipedOutputStream,任何写入其中的信息都会自动作为相关PipedInputStream的输出,实现“管道化”概念;
1.3 装饰器
除了有上面的基础构件,还有两个子类:FilterInputStream/FilterOutputStream,也是InputStream和OutputStream的子类,它们为“装饰器”(decorator)类提供基类,其中,“装饰器”类可以把属性或有用的接口与基础构件连接在一起。因为上面提到的InputStream/OutputStream是单字节为单位来操作的,而真实的I/O场景远不止于此,所以就通过“装饰”(其原理是类之间的组合)的方式来扩展其功能。
我自己梳理了一下InputStream/OutputStream流继承层次结构,结合下面的解释来看可以对字节流体系有一个更清晰的认识:
1.3.1 FilterInputStream
FilterInputStream类主要有如下子类,也就是具体装饰器:
DataInputStream;
BufferedInputStream;
LineNumberInputStream;
其提供的装饰功能主要在两个方面:
读取不同的基本类型数据以及String对象,比如DataInputStream;
在内部修改InputStream的行为方式:是否缓冲、是否保留它所读过的行,如BuffereInputStream、LineNumberInputStream;
1.3.2 FilterOutputStream
与FilterInputStream类似,FilterOutputStream主要是完成写入的功能,主要有如下装饰器:
DataOutputStream,与DataInputStream搭配使用,因此可以按照可移植方式向流中写入基本类型数据(int、char、long);
PrintStream,用于产生格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示;
BufferedOutputStream,使用它以避免每次发送数据时都要进行实际的写操作。代表“使用缓冲区”。可以调用flush()清空缓冲区;
2. Writer/Reader
InputStream和OutputStream是提供面向字节形式的I/O,但是InputStream/OutputStream流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化(Java本身的char也是16位的Unicode),所以添加Reader/Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。
几乎所有原始的Java I/O流类都有相应的Reader和Writer类来提供天然的Unicode操作,我们可以对比一下:
我们发现大体上,这两个不同的继承层次结构中的接口即使不能完全相同,但是也是非常相似的。
对于InputStream和OutputStream来说,我们会使用FilterInputStream和FilterOutputStream的装饰器子类来修改“流”以满足特殊需要。Reader/Writer的类继承层次结构继续沿用相同的思想,但是又并不完全采用上面说到的装饰器模式。如下是自己梳理的Reader/Writer继承层次结构:
与前面的I/O继承层次结构图相对比可以发现,尽管BufferedOutputStream是FilterOutputStream的子类,但是BufferedWriter并不是FilterWriter的子类(FilterWriter是抽象类,但是没有任何子类,仅仅是作为一个占位符)。
2.1 适配器
有时我们必须把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用。为了实现这个目的,要用到“适配器”(adapter)类:InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer。
感谢各位的阅读!关于“JavaI/O之输入和输出的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。