一、输入流与输出流
输入流将数据从文件、标准输入或其他外部输入设备中加载到内存。输出流的作用则刚好相反,即将在内存中的数据保存到文件中,或传输给输出设备。输入流在Java语言中对应于抽象类java.io.InputStream及其子类,输出流对应于抽象类java.io.OutputStream及其子类。抽象类java.io.InputStream与java.io.OutputStream定义了输入流和输出流的基本操作。
(1)InputStream和FileInputStream
因为java.io.InputStream是抽象类,所以不能通过“new InputStream()”的方式构造java.io.InputStream实例对象。但它定义了输入流的基本操作,如读数据(read)和关闭输入流(close)等。System.in是java.io.InputStream类型的变量,对应于标准输入,主要用于接受键盘的输入。
类java.io.FileInputStream是抽象类java.io.InputStream的子类。创建类java.io.FileInputStream的实例对象,可以通过类java.io.FileInputStream构造方法创建实例对象。对文件内容进行操作的基本步骤如下:
1)创建该文件所对应的输入/输出流或读写器的实例对象,以获得相关的系统资源,例如,存放该文件信息的内存空间以及对该文件的控制权限;
2)对该文件进行读(输入)/写(输出)操作;
3)最后调用close成员方法,关闭文件,以释放所占用的系统资源。
(2)OutputStream和FileOutputStream
抽象类java.io.OutputStream是用来处理输出流的类。它定义了输出流的各种基本操作,如:输出数据(write)和关闭输出流等。System.out是java.io.OutputStream类型的变量,对应于标准输出,主要用来在控制台窗口中输出信息。一般在调用抽象类java.io.OutputStream的write成员方法之后,常常会调用抽象类java.io.OutputStream的强制输出成员方法flush()。这往往是很有必要的,因为目前的计算机系统为提高运行效率,常常采用缓存机制。这样,在调用成员方法write之后,常常不会将数据直接输出或写入文件,而是暂时保存在缓存中。当数据积累到了一定程度时,才会真正往外输出数据。调用成员方法flush就是为了强制立即输出数据。这样,在调用成员方法flush之后,一般马上就可以看到输出结果。
类java.io.FileOutputStream是抽象类java.io.OutputStream的子类。创建类java.io.FileOutputStream的实例对象一般通过其构造方法完成,该实例对象可以调用相应的write成员方法将数据写入文件,并通过close成员方法关闭输出流。其对文件进行操作的步骤如下:
1)创建类java.io.FileOutputStream的实例对象,以获得相关的文件资源;
2)通过类java.io.FileOutputStream的write成员方法将数据写入文件中;在这中间,并通过类java.io.FileOutputStream的flush成员方法强制输出;
3)最后,调用类java.io.FileOutputStream的close成员方法,关闭文件,以释放所占用的系统资源。
创建类java.io.FileOutputStream的实例对象以及调用类java.io.FileOutputStream的write成员方法等可能产生异常。因此,一般需要采用try-catch结构或try-catch-finally结构处理相应的异常。
(3)PrintStream
类java.io.PrintStream是非常重要的输出流类。表示标准输出并用来在控制台窗口中输出信息的System.out是java.io.PrintStream类型的变量。类java.io.PrintStream具有非常良好的特性:
1)它包含可以用来直接输出多种类型数据的不同成员方法;
2)它的大部分成员方法不抛出异常;
3)可以选择是否采用自动强制输出(flush)特性。如果采用自动强制输出特性,则当输出回车换行时,在缓存中的数据一般会全部自动写入指定的文件或在控制台窗口中显示。
(4)数据的输入流和输出流
数据的输入流与输出流对应的类分别是类java.io.DataInputStream与java.io.DataOutputStream,主要用来读取与存储基本数据类型的数据,而且每个基本数据类型数据存储的字节数与它在内存中的占用字节数相同,例如:整数(int)类型的数据占用4个字节。因为数据流的存储格式采用统一的形式,所以数据的输入流与输出流的平台相关性较小。一般说来,输入流与输出流在使用上应当相互配套,例如:采用数据输入流(DataInputStream)读取数据输出流(DataOutputStream)存储的数据。
(5)带缓存的输入流和输出流
带缓存的输入流和输出流对应的类是java.io.BufferedInputStream和java.io.BufferedOutputStream。这两个类通过缓存机制进一步增强了输入流(Input Stream)和输出流(Output Stream)读取和存储数据的效率。当创建java.io.BufferedInputStream或java.io.BufferedOutputStream的实例对象时,均会在内存中开辟一个字节数组的存储单元(一般称为缓存),用来存放在数据流终中的数据。这样,借助于字节数组缓存,在读取或存储数据时可以将一个较大数据块读入内存中,或将在内存中较大数据块一次性写入指定的文件中,从而达到提高读/写效率的目的。
(6)标准输入输出流的重定向
类java.lang.System含有3个静态成员域in、out和err,分别表示标准输入流、标准输出流和标准错误输出流。标准输入流主要用来接受键盘的输入。标准输出流是用来在控制台窗口中输出信息。标准错误输出流是用来在控制台窗口中输出错误提示信息。因为它们都是类java.lang.System的静态成员域,所以都可以通过类名直接访问,即System.in、System.out和System.err。它们的类型分别是java.io.InputStream、java.io.PrintStream和java.io.PrintStream,因此可以通过调用这些类的成员方法进行各种操作。
标准输入流、标准输出流和标准错误输出流的重定向就是将这些标准输入流、标准输出流和标准错误输出流分别与指定的文件建立起对应关系;当需要输入数据时,数据将从文件中读取;当需要输出数据时,数据将写入文件。
二、读写器
前面说的输入流和输出流都是以字节为基本单位访问文件,可以认为它们所处理的是字节流。而读写器则是以字符为基本单位访问文件的,从而可以认为读写器处理的是字符流。
(1)Reader和Writer
抽象类java.io.Reader和抽象类java.io.Writer规定了读写器的一些基本操作。抽象类java.io.Reader用来读取数据,抽象类java.io.Writer用来存储数据。
不能直接用“new Reader()”或“new Writer()”生成抽象类java.io.Reader或抽象类java.io.Writer的实例对象,只能通过抽象类的子类生成它们子类的实例对象。
(2)FileReader和FileWriter
类java.io.FileReader和类java.io.FileWriter分别是抽象类java.io.Reader和抽象类java.io.Writer的子类。类java.io.FileReader兼容抽象类java.io.Reader的所有成员方法,可以进行读取字符和关闭字符流等操作。类java.io.FileWriter兼容抽象类java.io.Writer的所有成员方法,可以进行输出单个或多个字符、强制输出和关闭字符流等操作。
(3)带缓存的读写器
类java.io.BufferedReader、java.io.LineNumberReader和java.io.BufferedWriter是带缓存的读写器类。这些带缓存的类通过缓存机制进一步增强了读写器读取和存储数据的效率。类java.io.BufferedReader和类java.io.LineNumberReader继承抽象类java.io.Reader的所有成员方法,可以进行读取字符和关闭字符流等操作。类java.io.BufferedWriter继承抽象类java.io.Writer的所有成员方法,可以进行输出单个或多个字符、强制输出和关闭字符流等操作。
(4)PrintWriter
类java.io.PrintWriter是非常重要的字符流类。它与类java.io.PrintStream非常类似。类java.io.PrintStream在处理字节时更强一些,而类java.io.PrintWriter在字符处理中具有优越性。与类java.io.PrintStream相似,类java.io.PrintWriter具有非常良好的特性:
1)类java.io.PrintWriter的大部分成员方法不会抛出异常。如果需要检查是否有错误发生可以通过PrintWriter的成员方法public boolean checkError(),当有错误发生时,该成员方法返回true;否则,返回false。
2)类java.io.PrintWriter实现了类java.io.PrintStream的所有print成员方法,因此PrintWriter也具有可以直接输出多种类型数据的不同成员方法。
3)类java.io.PrintWriter的自动强制输出(flush)功能与类java.io.PrintStream的相应功能有所不同。当采用PrintWriter时,只有了其成员方法println、printf或format才可能自动强制输出。
(5)从控制台窗口读入数据
类java.io.InputStreamReader和java.io.OutputStreamWriter是从控制台读入数据的常用功能类,通过这两个类可以将输入流和输出流转换为相应的读写器,从而方便文本数据的处理。
三、文件
当需要读取数据的文件不存在时往往不能直接作出判断,而必须通过异常才能得到这种信息,而类java.io.File很好地解决了这个问题。类java.io.File一般不涉及文件内部的具体内容,而是从整体上对文件进行处理,如获取各种各样的文件信息或者删除文件。类java.io.File不仅可以对文件进行操作,而且还可以对路径进行操作。