一、流的概念
流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。
形象的比喻——水流 ,文件======程序 ,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出.便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。
"IO"对程序语言的设计者来说是一项难度极高的任务.编程思想中这样说过,可见要把IO彻底搞清楚并非简单之事.我也苦心研究过IO但是还不能完全理解.只是理解了主要的一些功能.File类的名字极具的富有欺骗性,刚看或许会认为是一个关于文件的类,但它不是.可以用它来表示某个文件的名字,也可以用它来表示目录里的一组文件的名字.如果它表示的是一组文件,那么你还可以用list()方法来进行查询,它返回String数组.File类的功能不仅限于显示文件或者目录.还可以帮你创建心的目录甚至是目录路径.此外还可以用来检查文件的属性,判断文件是否存在,删除文件等等N多功能.个人觉的IO流是J2SE的核心技术之一,虽然J2EE的程序员精通于它,但是掌握基本的流操作和原理也是很有必要的.说了半天什么是"流"呢?所谓"流"就是一种能生成或接受数据的,代表数据的源和目标的对象,流把I/O设备内部的具体操作封装了起来.JDK文档上说到JAVA的I/O类库分成输入和输出两大部分也就是通常说的读和写.所有的InputStream和Reader的派生类都有一个基本的继承来的能读取单个或者byte数组的read()方法.反之所有的OutputStream和Writer的派生类都有一个基本的能写入单个或byte数组的write()方法.
InputStream的任务就是代表那些从各种输入源获取数据的类,这些源主要有byte数组,String对象,文件,管道,流序列,Internet.这些数据源各自都有与之相对应的InputStream的子类.
1)ByteArrayInputStream:以缓冲区内存为InputStream
2)StringBufferInputStream:以String为InputStream
3)FileInputStream:专门用来读文件
4)PipedInputStream:从PipedOutputStream提取数据实现"管道"功能
5)SequenceInputStream:把两个或者多个InputStream合并成一个.
6)FilterInputStream:一个为decorator定义接口用的抽象类.
OutputStream是解决往哪里输出的类,是byte数组,文件或者是管道.
1)ByteArrayOutputStream:在内存里创建一个缓冲区,数据送到流里就是写入这个缓冲区.
2)FileOutputStream:把数据写入文件.
3)PipedOutputStream:写入这个流的数据,最终都会变成与之相关联的PipedInputStream的数据源.
4)FilterOutputStream:一个能decorator提供接口的抽象类.
自从java1.1对最底层的I/O流类库作了重大修改之后,我们看到了Reader和Writer,这个时候我们也许会想reader和writer是不是要取代InputStream和OutputStream呢?不过事实并非如此,虽然InputStream和OutputStream的部分功能已经被淘汰(你继续用编译会有异常),但是仍然有很多东西是有价值的,它们是面向byte的I/O流,也就是字节流.而Reader和Writer则提供的是Unicode的兼容,也就是字符类.Reader和Writer(我称为读流和写流)我觉的主要的用途在与国际化问题.而原来的I/O类库只支持8位的字节,也就是输入输出流,因为不能很好的处理16位的unicode字符.这里说一个概念就是"标准I/O"是Unix的概念,它的意思是一个程序使用一个信息流.所有输入都是从"标准输入"流进来的,输出都是从"标准输出"出去的.错误的消息有"标准错误"标准I/O的优点是可以很容易的和程序串连起来,并且把一个程序的输出当作另一个程序的输入.新IO是JAVA1.4引入的一个新的I/O类库,位于"java.nio.*"包,这么做只有一个目的就是速度.不过至于这个包中的类我还没具体的使用过HOHO.
JAVA的"对象系列化"能让一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,就可以从byte数据恢复出来,简单的说就是把对象保存在外部文件中.而且这种方法也是跨平台的,你无需考虑自己的对象文件应用于什么平台,这些技术细节虚拟机为我们实现了.序列化一个对象还是比较简单的,只要让它实现Serializable接口就行了(这是一个标记接口(tagging interface)没有方法的接口).但是,当语言引入序列化概念之后,它的很多标准类库的类,包括primitive的wrapper类,所有的容器类,以及别的很多类,都会相应地发生改变.甚至连Class对象都会被序列化.要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream.这时,你就能用writeObject( )方法把对象写入OutputStream了.读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject( )方法.不过这样读出来的,只是一个Object的对象.对象序列化的重要用途就是Bean技术和RMI(远程方法调用).
如果想深刻学习掌握JAVA的I/O流,我在这里推荐Elliotte Rusty Harold写的<<Java I/O>>(O’Reilly, 1999)这本书.
二、流的分类
java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流的原理也类似。
Java的常用输入、输出流
java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。
Java的字节流
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。
Java的字符流
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。
结合开始所说的输入/输出流 ,出现了个一小框架。
字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
JAVA字节流
FileInputStream和FileOutputStream
这两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。如:
要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。
BufferedInputStream和BufferedOutputStream
它们是过滤器流,其作用是提高输入输出的效率。
DataInputStream和DataOutputStream
这两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出。
Java的字符流
字符流主要是用来处理字符的。Java采用16位的Unicode来表示字符串和字符,对应的字符流按输入和输出分别称为readers和writers。
InputStreamReader和OutputStreamWriter
在构造这两个类对应的流时,它们会自动进行转换,将平台缺省的编码集编码的字节转换为Unicode字符。对英语环境,其缺省的编码集一般为ISO8859-1。
BufferedReader和BufferedWriter
这两个类对应的流使用了缓冲,能大大提高输入输出的效率。这两个也是过滤器流,常用来对InputStreamReader和OutputStreamWriter进行处理。如:
该程序接受键盘输入并回显。
对BufferedReader类,该类的readLine()方法能一次从流中读入一行,但对于BufferedWriter类,就没有一次写一行的方法,所以若要向流中一次写一行,可用PrintWriter类将原来的流改造成新的打印流,PrintWriter类有一个方法println(),能一次输出一行。如:
例子:
1,与控制台相关。的读入/写出。 实现了字符串的复制。
2,与文件 相关的 读写。 实现了文件的复制。
也是在一个百度好友上看到一篇关于流的文章写的更详细,把好多过时的不用的,哪写常用的都分类了,
还有好多类:
像RandomAccessFile类,序列化接口,都十分重要。
Java有一种特殊类型的IO数据流——DataOutputStream——它可以保证“无论数据来自何种机器,只要使用一个DataInputStream收取这些数据,就可用本机正确的格式保存它们.
以后在把示例加上,还有写比较好的方法。
其实感觉这已经是固定模式了,一提到从键盘读取数据 就会联想到:
现在水平达不到,还是记些固定格式比较好,以至于会用。
某个老师也说过,创新是建立在扎实的基础之上,越来越觉得基础重要了。