File类
1.File(文件)类,我们 可能会认为它指代对事文件,实际上却并非如此。它既能代表一个特定的文件对名称,又能代表一个目录下的一组文件的名称。
一.目录列表器
1.假设我们想要查看一个目录列表,可以用两种方法来使用File对象,如果我们调用不带参数的list()方法,便可获得此File对象包含的全部列表。然而,如果我们想获得一个受限列表,那么我们就要用到“目录过滤器”,这个类会告诉我们怎样显示符合条件的File对象:
public class DirList() {
public static void main(String... args) {
File path = new File(".");
String[] list;
if (args.length == 0) {
list = path.list();
} else {
list = path.list(new DirFilter(args[0]));
}
for (String dirItem : list)
System.out.println(dirItem);
}
}
class DirFilter implements FilenameFilter {
private Pattern pattern;
public DirFilter(String regex) {
pattern = Pattern.compile(regex);
}
public boolean accept(File dir, String name) {
return pattern.matcher(name).matches();
}
}
这里我们实现了FilenameFilter接口:
public interface FilenameFilter {
boolean accept(File dir, String name);
}
accept()方法必须接受一个代表某个特定文件所在的目录的File对象,以及包含了那个文件名的一个String。list()方法会为此目录对象下的每个文件名调用accept()方法,来判断文件是否包含在内;判断结果由accept()返回的布尔值表示。
二.目录实用工具
public final class Directory {
public static File[] local(File dir, String regex) {
return dir.listFiles(new FilenameFilter() {
private Pattern pattern = Pattern.compile(regex);
public boolean accept() {
return pattern.matcher(new File(name).getName()).matches();
}
})
}
public static File[] local(String path, final String regex) {
return local(new File(path), regex);
}
public static TreeInfo walk(String start, String regex) {
return recurseDirs(new File(start), regex);
}
public static TreeInfo walk(File start, String regex) {
return recurseDirs(start, regex);
}
public static TreeInfo walk(File start) {
return recurseDirs(new File(start), ".*");
}
public static TreeInfo walk(String start) {
return recurseDirs(new File(start), ".*");
}
static TreeInfo recurseDirs(File startDir, String regex) {
TreeInfo result = new TreeInfo();
for (File item : startDir.listFiles()) {
if (item.isDirectory()) {
result.dirs.add(item);
result.addAll(recurseDirs(item, regex));
} else {
if (item.getName().matches(regex)) {
result.files.add(item);
}
}
}
return result;
}
public static class TreeInfo implements Iterable<File> {
public List<File> files = new ArrayList<File>();
public List<File> dirs = new ArrayList<File>();
public Iterator<File> iterator() {
return files.iterator();
}
void addAll(TreeInfo other) {
files.addAll(others.files);
dirs.addAll(others.dirs);
}
}
}
在这里我们定义了一个工具类Directory,其中包含了两个方法:local()方法用来产生由本地目录中的文件构成的File对象数组;walk()方法产生给定目录下的由整个目录树中所有文件构成的List<File>。至于上面程序中使用到的关于File类的方法,根据方法名我们就能看出它们的用处。
三.目录的检查及创建
1.File类不仅仅只代表存在的文件或目录。也可以用File对象来创建新的目录或尚不存在的整个目录路径。我们还可以查看文件的特性,检查某个FIle对象代表的事一个文件还是一个目录,并可以删除文件。具体用法不再一一举出。
输入和输出
1.流是个抽象的概念,它代表任何由能力产出数据的数据源对象或者是有能力接收数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。
2.通过继承,任何自InputStream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的方法名,用于写单个字节或者字节数组。
3.使用流的特点:创建单一的结果流,却需要创建多个对象。
一.InputStream类型
1.InputStream的作用是用来表示那些从不同数据源产生输入的类。每一种数据源都有相应的InputStream子类:
类 | 功能 | 构造器参数及使用 |
---|---|---|
ByteArrayInputStream | 允许将内存的缓冲区当做InputStream使用 | 缓冲区子节将从中取出;作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口 |
StringBufferInputStream | 将String转换成InputStream | 字符串。底层实现实际使用StringBuffer;作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口 |
FileInputStream | 用于从文件中读取信息 | 字符串,表示文件名、文件或FileDescription对象;作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口 |
PipedInputStream | 产生用于写入相关PipedOutputStream的数据。实现“管道化” | PipedOutputStream;作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口 |
SequenceInputStream | 将一个或多个InputStream对象转换成单一InputStream | 两个InputStream对象或一个容纳InputStream对象的容器Enumeration;作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口 |
FilterInputStream | 抽象类,作为“装饰器”的接口。其中“装饰器”为其他的InputStream类提供有用的功能 | 见后续内容 |
二.OutputStream类型
1.该类别的类决定了输出所要去往的目标:
类 | 功能 | 构造器参数及使用 |
---|---|---|
ByteArrayOutputStream | 在内存中创建缓冲区。所有送往“流”的数据都要放置在此缓冲区 | 缓冲区初始化尺寸(可选);用于指定数据的目的地:将其与FilterOutputStream对象相连以提供有用的接口 |
FileOutputStream | 用于将信息写至文件 | 字符串,表示文件名、文件或FileDescription对象;指定数据的目的地:将其与FilterOutputStream对象相连以提供有用的接口 |
PipedOutputStream | 任何写入其中的信息都会自动作为相关PipedInputStream的输出。实现“管道化”的概念 | PipedInputStream;指定用于多线程的数据的目的地:将其与FilterOutputStream对象相连以提供有用的接口 |
FilterOutputStream | 抽象类,作为“装饰器”的接口。其中“装饰器”为其他的OutputStream类提供有用的功能 | 见后续内容 |
添加属性和有用的接口
1.FilterInputStream和FilterOutputStream是用来提供装饰器类接口以控制特定输入流河输出流的两个类,着两个类是装饰器的必要条件。
一.通过FilterInputStream从InputStream中读取数据
1.FilterInputStream类能够完成两种不同的事情:第一种是DataInputStream,这种类允许我们读取不同基本类型数据以及String对象,搭配相应的DataInputStream,我们就可以将基本类型的数据从一个地方迁移到另一个地方;另一种则在内部修改FilterInputStream的行为方式:是否缓冲,是否保留它所读过的行,以及是否把单一字符推回输入流等等:
类 | 功能 | 构造器参数及使用 |
---|---|---|
DataInputStream | 与DataOutputStream搭配使用,因此我们可以按照可移植的方式从流读取基本数据类型 | InputStream;包含读取基本类型数据的全部接口 |
BufferedInputStream | 使用它可以防止每次读区时都得进行实际写操作。代表“缓冲区” | InputStream,可以指定缓冲区的大小(可选);本质上不提供接口,只不过是向进程中添加缓冲区所必需的。与接口对象搭配 |
LineNumberInputStream | 跟踪输入流中的行号;可调用getLineNumber()和setLineNumber(int)** | InputStream;仅增加了行号,因此可能要与接口对象搭配使用 |
PushbackInputStream | 具有“能弹出一个字节的缓冲区”。因此可以将独岛的最后一个字符回退 | InputStream;通常作为编译器的扫描器,之所以包含在内是因为Java编译器的需要,我们可能永远不会用到 |
二.通过FilterOutputStream向OutputStream写入
1.DataOutputStream与上面的DataInputStream相对应。
2.PrintStream的目的便是为了以可视化的格式打印所有的基本数据类型以及String对象。内部有两个重要的方法:print()和println()。对它们进行了重载,以便打印出各种数据类型。
3.BufferedOutputStream,它对数据流使用缓冲技术;因此当每次向流写入时,不必每次都进行实际的物理写动作。
类 | 功能 | 构造器参数及使用 |
---|---|---|
DataOutputStream | 与DataInputStream搭配使用,因此我们可以按照可移植的方式从流写入基本数据类型 | OutputStream;包含用于写入基本数据类型的全部接口 |
PrintStream | 用于产生格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示 | OutputStream,可以用boolean值指示是否在每次换行时清空缓冲区 |
BufferedOutputStream | 使用它以避免每次发送数据时都要进行实际的写操作。代表“使用缓冲区”。可以调用flush()清空缓冲区 | OutputStream,可以指定缓冲区的大小(可选);本质上并不提供接口,只不过是向进程中添加缓冲区所必需的。与即可哦哭对象搭配 |
Reader和Writer
1.InputStream和OutputStream在以面向字节形式的I/O中可以提供极有价值的功能,Reader和Writer则提供兼容Unicode与面向字符的I/O功能。
2.InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer。这样就可以把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用。
一.数据的来源和去处
1.在使用I/O流的时候,最明智的做法是尽量尝试使用Reader和Writer,一旦程序代码无法编译成功,就不得不使用面向字节的类库。
2.下面的表中展示了各种两种不同层次结构中,信息的来源和去处的对应关系:
字节类Java 1.0 | 相应的字符类Java 1.1 |
---|---|
InputStream | Reader;适配器:InputStreamReader |
OutputStream | Writer;适配器:OutputStreamWriter |
FileInputStream | FileReader |
FileOutputStream | FileWriter |
StringBufferInputStream(已弃用) | StringReader |
(无相应的类) | StringWriter |
ByteArrayInputStream | CharArrayReader |
ByteArrayOutputStream | CharArrayWriter |
PipedInputStream | PipedReader |
PipedOutputStream | PipedWriter |
二.更改流的行为
1.在更改“流”的行为方面,Writer和Reader的类继承层次结构继续沿用了和InputStream和OutputStream的思想——使用“装饰器”来修改“流”的特殊需要:
过滤器Java 1.0 | 相应的Java 1.1类 |
---|---|
FilterInputStream | FilterReader |
FilterOutputStream | FilterWriter(抽象类, 没有子类) |
BufferedInputStream | BufferedReader(也有readLine()) |
BufferedOutputStream | BufferedWriter |
DataInputStream | 使用DataInputStream(除了当需要使用readLine()时以外,这时应该使用BufferedReader) |
PrintStream | PrintWriter |
LineNumberInputStream(已弃用) | LineNumberWriter |
StreamTokenizer | StreamTokenizer(使用接受Reader的构造器) |
PushbackInputStream | PushbackReader |
2.上面的表中已经指出:无论何时使用功能readLine(),都不应该使用DataInputStream,而应该使用BufferedReader。除此以外,DataInputStream仍然是I/O库的首选。
三.未发生变化的类
未作出改变的类 |
---|
DataInputStream |
File |
RandomAccessFile |
SequenceInputStream |
特别是DataInputStream,在使用时没有人和变化;因此如果想以“可传输到”格式存储和检索数据,可以使用InputStream和OutputStream继承层次结构。