Path 接口和 Files 类封装了在用户机器上处理文件系统所需的所有功能,他们是在 Java SE 7 中新添加进来的,比自 JDK1.0 以来一直使用的 File 类方便很多。
1 Path
Path 表示的是一个目录名序列,其后还可以跟着一个文件名。
路径中的第一个部件可以是根部件,例如 /
或 C:\
。以根部件开始的路径是绝对路径;否则,就是相对路径。
Path absolute = Paths.get("/home","harry");
Path relative = Paths.get("myprog","conf","user.properties");
静态的 Paths.get 方法接受一个或多个字符串,并将它们用默认文件系统的路径分隔符(/
,\
)连接起来。
1.1 绝对路径(resolve)
组合或解析路径,调用 p.resolve(q) 将按照下列规则返回一个路径:
- 如果 q 是绝对路径,结果就是 q
- 否则,根据文件系统规则,将“p 后跟 q"作为结果
1.2 绝对兄弟路径(resolveSibling)
解析指定路径的父路径产生其兄弟路径
Path workPath = Paths.get("/opt/myapp/work");
Path tempPath = workPath.resolveSibling("temp");
//tempPath == /opt/myapp/temp.
1.3 相对路径(relativize)
resolve 的对立面,即调用 p.relativize® 将产生路径 q,而对 q 进行的解析的结果正是 r。
例如,以“/home/cay”为目标对“/home/fred/myprog”进行相对化操作,会产生“…/fred/yprog",其中假设 ..
表示的是文件系统的父目录。
1.4 规范化(normalize)
移除所有冗余的 .
和 ..
部件(或者文件系统认为冗余的所有部件)。
例如,规范化“/home/cay/…/fred/./myprog”将产生“/home/fred/myprog”。
1.5 根目录绝对路径(toAbsolutePath)
产生给定路径的绝对路径,该绝对路径从根目录开始。
例如“/home/fred/input.txt”或“c:\Usersfredinput.txt”。
1.6 断开路径
Path 类有许多有用的方法用来将路径断开。
Path p = Paths.get("/home","fred","myproperties");
Path parent = p.getParent();
Path file = p.getFileName();
Path root = p.getRoot();
1.7 Scanner
还可以从 Path 对象中构建 Scanner 对象:
Scanner in = new Scanner(Paths.get("/home/fred/input.txt"));
1.7 遗留系统
需要与遗留系统交互时,可以使用 Path 的 toFile 方法,或者 File 类的 toPath 方法
2 Files
2.1 读写文件
Files 类可以使得普通文件操作变得快捷。
1)读
- 读为byte
byte[] bytes = Files.readAllBytes(path);
- 读为字符串
String content = new String(bytes,charset);
- 读为行
List<String> lines = Files.readAllLines(path,charset);
2)写
- 写出字符串
Files.write(path,content.getBytes(charset));
- 追加内容
Files.write(path,content,getBytes(charset),StandardOpenOption.APPEND);
- 写出行集合
Files.write(path,lines);
3)大文本
Files 类的简便方法适用于处理中等长度的文本文件,如果要处理的文本长度较大,或者是二进制文件,还是应该使用所熟知的输入输出流或者读入器、写出器。
InputStream in = Files.newInputStream(path);
OutputStream out = Files.newOutputStream(path);
Reader in = Files.newBufferedReader(path, charset);
Writer out = Files.newBufferedWriter(path, charset);
2.2 创建文件和目录
1)创建新目录
中间目录必须是已存在
Files.createDirectory(path);
同时创建中间目录
Files.createDirectories(path);
2)创建空文件
如果文件已存在,会抛异常。
Files.createFile(path);
检查文件是否存在和创建文件是原子性的,如果文件不存在,该文件就会被创建,并且其他程序在此过程中是无法执行文件创建操作的。
3)创建临时文件和临时目录
Path newPath = Files.createTempFile(dir,prefix,suffix);
Path newPath = Files.createTempFile(prefix,suffix);
Path newPath = Files.createTempDirectory(dir,prefix);
Path newPath = Files.createTempDirectory(prefix);
其中,dir 是一个 Path 对象,prefix 和 suffix 是可以为 null 的字符串。例如,调用 Files.createTempFile(null, “.txt”) 可能会返回一个像“/tmp/1234405522364837194.txt”这样的路径。
创建文件或目录,可以制定属性,例如文件的拥有者和权限。
2.3 复制、移动和删除文件
1)复制
- Files.copy(fromPath,toPath):复制文件
- Files.copy(inputStream,toPath):将输入流复制到 Path 中,输入流存储到硬盘上
- Files.copy(fromPath,outputStream):将 Path 复制到输出流中
StandardCopyOption
- REPLACE_EXISTING:覆盖已有的目标路径
- COPY_ATTRIBUTES:复制所有的文件属性
- ATOMIC_MOVE:将移动操作定义为原子性的
2)移动
如果目标路径已经存在,那么复制或移动将失败。
Files.move(fromPath,toPath);
3)删除
- 删除文件
Files.delete(path);
如果要删除的文件不存在,会抛异常。
- 删除存在文件
boolean deleted = Files.deleteIfExits(path);
2.4 获取文件信息
1)路径属性
- exists
- isHidden
- isReadadble,isWritable,isExecuutable
- isRegularFile, isDirectory, isSymbolicLink
2)文件字节数
size方法
long filesize = Files.size(path);
3)文件拥有者
getOwner 方法将文件的拥有者作为 java.nio.file.attribute.UserPrincipal 的一个实例返回。
4)基本属性集
获取基本属性集
- 创建文件、最后一次访问、最后一次修改的时间,这些时间都表示成 java.nio.file.attribute.FileTime
- 文件是常规文件、目录还是符号链接,或者都不是
- 文件尺寸
- 文件主键,这是某种类的对象,具体所属类与文件系统相关,有可能是文件的唯一标识符,也可能不是
BasicFileAttributes attributes = Files .readAttributes(path,BasicFileAttributes.class);
如果文件系统兼容 POSIX,可获取 PosixFileAttributes 实例:
PosixFileAttributes attributes = Files .readAttributes(path,PosixFilesAttributes.class);
然后从中找到拥有者,以及文件的拥有者、组或访问权限。
2.5 访问目录中的项
1)list
Files.list 方法会返回一个可以读取目录中各个项的 Stream
list 方法不会进入子目录。
try( Stream<Path> entries = Files.list(pathToDirectory){...}
2)walk
Files.walk 方法会产生一个可以遍历目录中所有子目录的 Stream
try( Stream<Path> entries = Files.walk方法(pathToRoot){...}
限制想要访问的树的深度。
File.walk(pathToRoot, depth)
2.6 使用目录流
要对遍历过程进行更加细粒度的控制,应该使用 File.newDirectoryStream 对象,它会产生一个 DirectoryStream。
1)DirectoryStream
DirectoryStream 不是 java.util.stream.Stream 的子接口,而是专门用于目录遍历的接口。它是 Iterable 的子接口,可以在增强的 for 循环中使用目录流。
try (DirectoryStream<Path> entries = Files.newDirectoryStream(dir)){
for (Path entry: entries){
Process entries
}
}
访问目录中的 项并没有具体的顺序。
2)过滤文件
可以用 glob 模式来过滤文件:
try (DirectoryStream<Path> entries = Files.newDirectoryStream(dir,"*.java"))
2.7 ZIP 文件系统
1)建立文件系统
FileSystem fs = FileSystem.newFileSystem(Path.get(zipname),null);
2)复制文件
Files.copy(fs.getPath(soureceName),targetPath);
fs.getPath 与 Paths.get 类似
3)遍历文件树
FileSystem fs = FileSystem.newFileSystem(Path.get(zipname),null);
Files.walkFileTreee(fs.getPath("/"),new SimpleFileVisitor<Path>(){
public FileVisitResult visitFile(Path file,BasicFileAttributes attrs) throws IOException{
System.out.pintln(file);
return FileVisitResult.CONTINUE;
}
});