文件
路径¶
-
Path路径表示文件、目录的路径,可以在不同操作系统上工作
-
从String或URI对象创建路径
Path p = Paths.get(xx)
-
JDK11之后
Path.of(xx)
-
使用String设置多级路径
-
Paths.get("C:", "path", "to", "nowhere", "NoFile.txt")
-
方法
p.isAbsolute();//是否为绝对路径 p.getFileName();//获取文件名称 p.getParent();//获取上级路径 p.getRoot();//获取最顶层路径(如 c:/) p.toRealPath();//获取绝对路径(取决于操作系统环境) p.normalize();//规范路径 URI u = p.toUri(); Path puri = Paths.get(u);
-
切割
for(int i = 0; i < p.getNameCount(); i++) System.out.println(p.getName(i));
-
也可以直接使用for-in循环遍历
-
注意对路径使用startsWith、endsWith要求是完整一项,如
xx.java
-
遍历的内容不包含根路径
-
添加/删除路径
- relativize(Path other):
relativize
方法用于构建两个路径之间的相对路径。如果你有两个路径A
和B
,调用A.relativize(B)
将返回一个路径,它从A
导航到B
的相对路径。它假设两个路径有一个共同的根,且不会在结果中包含根路径部分。 - resolve(Path other):
resolve
方法用于将一个路径附加到另一个路径的末尾。如果你有两个路径A
和B
,调用A.resolve(B)
会创建一个合并了两个路径的新Path
对象,如果B
是绝对路径,则直接返回B
。
Files工具类¶
say("Exists", Files.exists(p));
say("Directory", Files.isDirectory(p));
say("Executable", Files.isExecutable(p));
say("Readable", Files.isReadable(p));
say("RegularFile", Files.isRegularFile(p));
say("Writable", Files.isWritable(p));
say("notExists", Files.notExists(p));
say("Hidden", Files.isHidden(p));
say("size", Files.size(p));
say("FileStore", Files.getFileStore(p));
say("LastModified: ", Files.getLastModifiedTime(p));
say("Owner", Files.getOwner(p));
say("ContentType", Files.probeContentType(p));
say("SymbolicLink", Files.isSymbolicLink(p));
- 遍历目录
Files.walkFileTree(Path, SimpleFileVisitor<Path>)
-
需要创建并传入一个(匿名类)SimpleFileVisitor\
preVisitDirectory
:在访问目录之前调用。visitFile
:在访问文件时调用。visitFileFailed
:在文件访问失败时调用。postVisitDirectory
:在访问目录之后调用。
-
示例:删除文件夹
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; } }); }
-
创建
Path newFilePath = Paths.get("newfile.txt"); Files.createFile(newFilePath); //如果文件已存在,抛 FileAlreadyExistsException Path newDirPath = Paths.get("newdir"); Files.createDirectory(newDirPath); //创建多级目录 Path dirsPath = Paths.get("newdir/subdir"); Files.createDirectories(dirsPath); //删除文件或目录 Path pathToDelete = Paths.get("fileOrDirToDelete"); Files.delete(pathToDelete); //删除目录时,目录必须是空的,否则会抛出 DirectoryNotEmptyException
-
Files.walk提供更简单的遍历方式
- 返回
Stream<Path>
对象Path start = Paths.get("/some/path"); try (Stream <Path> stream = Files.walk(start, 3)) { // 遍历深度为 3 stream.forEach(System.out:: println); // 打印每个文件和目录的路径 }
//删除 txt 文件
static Path test = Paths.get("test");
static void delTxtFiles() {
try {
Files.walk(test)
.filter(f ->
f.toString().endsWith(".txt"))
.forEach(f -> {
try {
System.out.println("deleting " + f);
Files.delete(f);
} catch(IOException e) {
throw new RuntimeException(e);
}
});
} catch(IOException e) {
throw new RuntimeException(e);
}
}
文件系统¶
- 获取文件系统对象
FileSystem fsys = FileSystems.getDefault();
-
也可以通过path、uri等获取
-
监听Path(文件目录的变化)
-
注意只会检测目标目录下的变化(不含子目录)
try { WatchService watcher = FileSystems.getDefault().newWatchService(); dir.register(watcher, ENTRY_DELETE); Executors.newSingleThreadExecutor().submit(() -> { try { WatchKey key = watcher.take(); for(WatchEvent evt : key.pollEvents()) { System.out.println( "evt.context(): " + evt.context() + "\nevt.count(): " + evt.count() + "\nevt.kind(): " + evt.kind()); System.exit(0); } } catch(InterruptedException e) { return; } }); } catch(IOException e) { throw new RuntimeException(e); }
-
查找文件
- 使用PathMatcher
//创建匹配模式,**/表示所有子目录,*.表示任意文件名称 PathMatcher matcher = FileSystems.getDefault() .getPathMatcher(" glob:**/*.{tmp, txt}"); Files.walk(test)//从特定目录遍历所有路径 .filter(matcher:: matches)//匹配路径 .forEach(System.out:: println);
PathMatcher matcher2 = FileSystems.getDefault()
.getPathMatcher(" glob:*.tmp ");
Files.walk(test) // 只匹配文件名
.filter(Files:: isRegularFile)
.map(Path:: getFileName)//将路径映射为文件名,下面才能正常进行匹配
.filter(matcher2:: matches)
.forEach(System.out:: println);
读写文件¶
- 读取整个文件
Files.readAllLines(Path)
- 会返回一个
List<String>
(行划分) - 可以直接创建一个流
.stream()
便于操作 -
是一次性将整个文件读取到内存,可能存在性能问题
-
逐行读取文件
- 将文件变成由行组成的stream
- 逐行读取,性能更好
-
Files.lines(Path).skip...
-
写入文件
- 可以将实现了Iterable接口的对象写入文件
Files.write(Path,comtent);