转自 开发者的天空
前面我们讨论了怎样对文件进行操作,下面我们来看看怎样对目录进行操作。首先我们来看看怎样列出一个文件系统中所有的更目录,就象我们在 Windows中 看到有多少硬盘分区(包括光盘等)。要得到这些信息,可以调用
FileSystem.getRootDirectories 方法。该方法返回一个 Iterable对象,我们可以遍历该对象得到所有的根目录。该对象中的 每个元素都是一个 Path对象。具体的代码例子如下:
import java.nio.file.FileSystems;
import java.nio.file.Path;
public class RootDirectoryReader {
public static void main(String[] args){
Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
for (Path name: dirs) {
System.err.println(name);
}
}
}
在 我的机器上运行该代码的输出如下:
C:\
D:\
E:\
F:\
G:\
在我的机器上, C盘是本地硬盘, D盘是光驱,其他 3个是移动硬盘的分区。
我们可以调用 Path类的 createDirectory方法来创建文件。如果调用该方法是不传递任何参数,那么生成 的新的目录就拥有默认的属性。下面的代码就是创建一个拥有默认属性的新目录:
Path dir = Paths.get("C:\\temp");
try {
path.createDirectory();
} catch (IOException x) {
System.err.println(x);
}
下 面的代码是在 POSIX文件系统上创建一个拥有指定的属性的目录:
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
try {
file.createDirectory(attr);
} catch (IOException x) {
System.err.println(x);
}
要 想创建一个多层的目录,如 c:\temp\first\abc这样的目录,我们可以使用 Files类的 createDirectories方法。这个方法 接受 Path类作为第一个参数,第二个参数是可选的参数 FileAttribute。下面的代码创建具有缺省属性的多层目录:
try {
Files.createDirectories(Paths.get("c:\\temp\\first\\abc"));
} catch (IOException x) {
System.err.println(x);
}
从 最上层开始,如果目录不存在,这创建新的目录。例如如果上面的目录层次中, c:\temp已经存在,则不再创建; c:\temp\first不存在,则直 接在 c:\temp下创建 first目录,然后在 first目录下创建 abc目录。
调用该方法的时候要注意该方法并不是原子操作,也就是说目录层次可能有一部分成功,一部分失败。如上面的例子中,可能 first目录创建成功了,但是 abc目录创建失败了。
要想列出目录中所有的内容,可以调用 newDirectoryStream()方法。该方法返回一个实现了 DirectoryStream接口的对象。实 现了 DirectoryStream的对象同时也实现了 Iterable接口,因此我们可以遍历该对象。遍历时得到的元素都是 Path对象。同时要注意的 是返回的 DirectoryStream也是一个流对象,别忘记使用完之后关闭该对象。
下面是示例代码:
Path dir = Paths.get("c:\\");
DirectoryStream<Path> stream = null;
try {
stream = dir.newDirectoryStream();
for (Path file: stream) {
System.out.println(file.getName());
}
} catch (IOException x) {
//IOException can never be thrown by the iteration.
//In this snippet, it can only be thrown by newDirectoryStream.
System.err.println(x);
} finally {
if (stream != null) stream.close();
}
如果我们查找名字符合某些模式的文件或者只目录,我们可以调用 newDirectoryStream(String)方法。这个方法会调用一个内置的过滤 器来过滤返回的结果。关于模式的使用我们在前面的文章里已经讲过了。下面是具体的例子:
Path dir = ...;
DirectoryStream<Path> stream = null;
try {
stream = dir.newDirectoryStream("*.{java,class,jar}");
for (Path entry: stream) {
System.out.println(entry.getName());
}
} catch (IOException x) {
//IOException can never be thrown by the iteration.
//In this snippet, it can only be thrown by newDirectoryStream.
System.err.println(x);
} finally {
if (stream != null) stream.close()
}
在 这个例子中,我们只返回以 .java或 .class或 .jar结尾的文件或子目录。
我们还可以实现自己的过滤器。例如如果我们只需要得到所有的子目录,对于文件我们不需要返回,我们就可以编写自己的过滤器。自己的过滤器要实现 DirectoryStream.Filter<T>接口,这个接口只有一个方法 accept,这个方法决定一个文件 /目录是否符合查询条 件。下面是具体的代码:
DirectoryStream.Filter<Path> filter = newDirectoryStream.Filter<Path>() {
public boolean accept(Path file) {
try {
boolean isDirectory = Attributes.readBasicFileAttributes(file).isDirectory();
return (isDirectory);
} catch (IOException x) {
//Failed to determine if it's a directory.
System.err.println(x);
return false;
}
}
}
当 过滤器创建好之后,我们可以通过 newDirectoryStream(DirectoryStream.Filter<? super Path>)方法来使用它。下面就是一个实现的例子:
Path dir = ...;
DirectoryStream<Path> stream = null;
try {
stream = dir.newDirectoryStream(filter);
for (Path entry: stream) {
System.out.println(entry.getName());
}
} catch (IOException x) {
System.err.println(x);
} finally {
stream.close();
}