本章探究为输入/输出操作提供支持的java.io包。在第12章,我们介绍了Java 的输入/输出系统。现在,我们要更深入的研究Java输入/输出系统。所有的程序员都知道,多数程序在不获取外部数据的情况下不能顺利完成目标。数据从一个输入源获得。程序的结果被送到输出目的地。Java中,这些源和目的地被广泛的定义。例如一个网络连接器,内存缓冲区或磁盘文件可以被Java输入/输出类熟练的操作。尽管从物理上很难说明,这些外设都由相同的抽象体流(stream)来处理。流,在第12章解释过,是一个生产或消费信息的逻辑实体。流通过Java输入/输出系统与物理设备相连。尽管与之相连的实际的物理设备各不相同,所有的流都以同样的方式运转。
注意:Java流式输入/输出的概述,参看第12章。
17.1 Java输入/输出类和接口
java.io定义的输入/输出类列于下表:
BufferedInputStream FileWriter PipedInputStream
BufferedOutputStream FilterInputStream PipedOutputStream
BufferedReader FilterOutputStream PipedReader
BufferedWriter FilterReader PipedWriter
ByteArrayInputStream FilterWriter PrintStream
ByteArrayOutputStream InputStream PrintWriter
CharArrayReader InputStreamReader PushbackInputStream
CharArrayWriter LineNumberReader PushbackReader
DataInputStream ObjectInputStream RandomAccessFile
DataOutputStream ObjectInputStream.GetField Reader
File ObjectOutputStream SequenceInputStream
FileDescriptor ObjectOutputStream.PutField SerializablePermission
FileInputStream ObjectStreamClass StreamTokenizer
FileOutputStream ObjectStreamField StringReader
FilePermission OutputStream StringWriter
FileReader OutputStreamWriter Writer
ObjectInputStream.GetField 和ObjectOutputStream.PutField 是Java 2新添的内部类。java.io包还包含两个不受java 2欢迎的类,这两个类没有在上表中列出:LineNumber InputStream和StringBufferInputStream。新代码不应该使用两个类。
下面是由java.io定义的接口:
DataInput FilenameFilter ObjectOutput
DataOutput ObjectInput ObjectStreamConstants
Externalizable ObjectInputValidation Serializable
FileFilter
FileFilter接口是Java 2新增的。java.io包中有很多类和接口。包括字节和字符流,对象序列化(对象的存储和释放)。本章讲述几个最常用的I/O成员,从最独特的File开始。
17.2 File(文件类)
尽管java.io定义的大多数类是实行流式操作的,File类不是。它直接处理文件和文件系统。也就是说,File类没有指定信息怎样从文件读取或向文件存储;它描述了文件本身的属性。File对象用来获取或处理与磁盘文件相关的信息,例如权限,时间,日期和目录路径。此外,File还浏览子目录层次结构。很多程序中文件是数据的根源和目标。尽管它们在小应用程序中因为安全原因而受到严格限制,文件仍是存储固定和共享信息的主要资源。Java中的目录当成File 对待,它具有附加的属性——一个可以被 list( )方法检测的文件名列表。
下面的构造函数可以用来生成File 对象:
File(String directoryPath)
File(String directoryPath, String filename)
File(File dirObj, String filename)
这里,directoryPath是文件的路径名,filename 是文件名,dirObj 一个指定目录的File 对象。下面的例子创建了三个文件:f1,f2,和f3。第一个File对象是由仅有一个目录路径参数的构造函数生成的。第二个对象有两个参数——路径和文件名。第三个File对象的参数包括指向f1文件的路径及文件名。f3和f2指向相同的文件。
File f1 = new File("/");
File f2 = new File("/","autoexec.bat");
File f3 = new File(f1,"autoexec.bat");
注意:Java 能正确处理UNIX和Windows/DOS约定路径分隔符。如果在Windows版本的Java下用斜线(/),路径处理依然正确。记住,如果你用Windows/DOS使用反斜线(\)的约定,你需要在字符串内使用它的转义序列(\\)。Java约定是用UNIX和URL风格的斜线来作路径分隔符。
File 定义了很多获取File对象标准属性的方法。例如getName( )返回文件名,getParent( )返回父目录名,exists( )在文件存在的情况下返回true,反之返回false。然而File类是不对称的。说它不对称,意思是虽然存在允许验证一个简单文件对象属性的很多方法,但是没有相应的函数来改变这些属性。下面的例子说明了几个File方法:
// Demonstrate File.
import java.io.File;
class FileDemo {
static void p(String s) {
System.out.println(s);
}
public static void main(String args[]) {
File f1 = new File("/java/COPYRIGHT");
p("File Name: " + f1.getName());
p("Path: " + f1.getPath());
p("Abs Path: " + f1.getAbsolutePath());
p("Parent: " + f1.getParent());
p(f1.exists() ? "exists" : "does not exist");
p(f1.canWrite() ? "is writeable" : "is not writeable");
p(f1.canRead() ? "is readable" : "is not readable");
p("is " + (f1.isDirectory() ? "" : "not" + " a directory"));
p(f1.isFile() ? "is normal file" : "might be a named pipe");
p(f1.isAbsolute() ? "is absolute" : "is not absolute");
p("File last modified: " + f1.lastModified());
p("File size: " + f1.length() + " Bytes");
}
}
运行该程序,你将看到下面的结果:
File Name: COPYRIGHT
Path: /java/COPYRIGHT
Abs Path: /java/COPYRIGHT
Parent: /java
exists
is writeable
is readable
is not a directory
is normal file
is absolute
File last modified: 812465204000
File size: 695 Bytes
大多数File方法是自说明的,但isFile( )和isAbsolute( )不是。isFile( )在被文件调用时返回true,在被目录调用时返回false。并且,isFile( )被一些专用文件调用时返回false,例如设备驱动程序和命名管道,所以该方法可用来判定文件是否作为文件执行。isAbsolute( )方法在文件拥有绝对路径时返回true,若是相对路径则返回false。File 还包括两个有用的实用工具方法。第一个是renameTo( ),显示如下:
boolean renameTo(File newName)
这里,由newName指定的文件名变成了所调用的File 对象的新的名称。如果更名成功则返回ture,文件不能被重命名(例如,你试图重命名文件以使它从一个目录转到另一个目录,或者你使用了一个已经存在的文件名),则返回false。第二个实用工具方法是delete( ),该方法删除由被调用的File对象的路径指定的磁盘文件。它的形式如下:
boolean delete( )
同样可以在目录为空时用delete( )删除目录。如果删除了文件,delete( )返回true,如果文件不能被删除则返回false。Java 2 为File 类增添了一些新的方法,你会发现在某些场合这些新增方法很有用。一些最有趣的方法显示如下:
方法 描述
void deleteOnExit( ) 在java虚拟机终止时删除与调用对象相关的文件
boolean isHidden( ) 如果调用的文件是隐藏的,返回true;否则返回 false。
boolean setLastModified(long millisec) 设置由millisec指定的调用文件的时间标志,Millisec是从1970年1月1号开始的标准时间(UTC)的毫秒数
boolean setReadOnly( ) 设置调用文件为只读