第十七章 文件
在Java7中对 文件的操作 引入了巨大的改进。这些新元素被放在 java.nio.file
包下面,过去人们通常把nio
中的n
理解为new
即新的io,现在更应该当成是non-blocking
非阻塞io(io就是input/output输入/输出)。
文件操作的两个基本组件:
- 文件或者目录的路径;
- 文件本身。
文件和目录路径
Paths
一个Path
对象表示一个文件或者目录的路径,是一个跨操作系统(OS)和文件系统的抽象,目的是在构造路径时不必关注底层操作系统,代码可以在不进行修改的情况下运行在不同的操作系统上。java.nio.file.Paths
类包含一个重载方法static get()
,该方法方法接受一系列Strings字符串或一个统一资源标识符(URI)作为参数,并且进行转换返回一个Path
对象。
选取路径部分片段
public class PartsOfPaths {
public static void main(String[] args) {
System.out.println(System.getProperty("os.name"));
Path p = Paths.get("PartsOfPaths.java").toAbsolutePath();
for (int i = 0; i < p.getNameCount(); i++)
System.out.println(p.getName(i));
System.out.println("ends with '.java': " + p.endsWith(".java"));
for (Path pp : p) {
System.out.print(pp + ": ");
System.out.print(p.startsWith(pp) + " : ");
System.out.println(p.endsWith(pp));
}
System.out.println("Starts with " + p.getRoot() + " " + p.startsWith(p.getRoot()));
}
}
可以通过getName()
来索引Path
的各个部分,直到达到上限getNameCount()
。Path
也继承了Iterable
接口,因此我们也可以通过增强的for循环进行遍历。请注意,即使路径以 .java结尾,使用endsWith()
方法也会返回 false 。这是因为使用endsWith()
比较的是整个路径部分,而不会包含文件路径的后缀。通过使用startsWith()
和endsWith()
也可以完成路径的遍历。但是我们可以看到,遍历Path对象并不包含根路径,只有使用 startsWith()
检测根路径时才会返回 true 。
路径分析
Files
工具类包含一系列完整的方法用于获得Path
相关的信息。
Paths的增减修改
public class AddAndSubtractPaths {
static Path base = Paths.get("..", "..", "..").toAbsolutePath().normalize();
static void show(int id, Path result) {
if (result.isAbsolute())
System.out.println("(" + id + ")r " + base.relativize(result));
else
System.out.println("(" + id + ") " + result);
try {
System.out.println("RealPath: " + result.toRealPath());
} catch (IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) {
System.out.println(System.getProperty("os.name"));
System.out.println(base);
Path p = Paths.get("src","files","AddAndSubtractPaths.java").toAbsolutePath();
show(1, p);
Path convoluted = p.getParent().getParent().resolve("strings").resolve("..")
.resolve(p.getParent().getFileName());
show(2, convoluted);
show(3, convoluted.normalize());
Path p2 = Paths.get("..", "..");
show(4, p2);
show(5, p2.normalize());
show(6, p2.toAbsolutePath().normalize());
Path p3 = Paths.get(".").toAbsolutePath();
Path p4 = p3.resolve(p2);
show(7, p4);
show(8, p4.normalize());
Path p5 = Paths.get("").toAbsolutePath();
show(9, p5);
show(10, p5.resolveSibling("strings"));
show(11, Paths.get("nonexistent"));
}
}
目录
删除文件或目录:
public class RmDir {
public static void rmdir(Path dir) throws IOException {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
}
文件系统
使用FileSystems
工具类获取"默认"文件系统"。
public class FileSystemDemo {
static void show(String id, Object o) {
System.out.println(id + ": " + o);
}
public static void main(String[] args) {
System.out.println(System.getProperty("os.name"));
FileSystem fsys = FileSystems.getDefault();
for (FileStore fs : fsys.getFileStores())
show("File Store", fs);
for (Path rd : fsys.getRootDirectories())
show("Root Directory", rd);
show("Separator", fsys.getSeparator());
show("UserPrincipalLookupService", fsys.getUserPrincipalLookupService());
show("isOpen", fsys.isOpen());
show("isReadOnly", fsys.isReadOnly());
show("FileSystemProvider", fsys.provider());
show("File Attribute Views", fsys.supportedFileAttributeViews());
}
}
路径监听
通过 WatchService
可以设置一个进程对目录中的更改做出响应。
文件查找
通过在 FileSystem
对象上调用 getPathMatcher()
获得一个 PathMatcher
,然后传入您感兴趣的模式。模式有两个选项:glob
和 regex
。
文件读写
Files.readAllLines()
一次读取整个文件(因此,“小”文件很有必要),产生一个List<String>
。 有一个 readAllLines()
的重载版本,它包含一个 Charset
参数来存储文件的Unicode编码。
Files.write()
被重载以写入 byte
数组或任何 Iterabl
e 对象(它也有 Charset 选项)。
Files.lines()
方便地将文件转换为行的 Stream
。