一、Path、Paths、Files核心API
Path接口代表一个平台无关的路径,Files类包含了大量静态的工具方法来操纵文件;Paths则包含了两个返回Path的静态工厂方法。下面试一试
package NIOTest; import java.nio.file.Path; import java.nio.file.Paths; public class PathTest { public static void main(String[] args) throws Exception{ Path path = Paths.get("."); System.out.println("path里包含的路径数量:"+ path.getNameCount()); System.out.println("path的根路径:" + path.getRoot()); Path absolutePath = path.toAbsolutePath(); System.out.println(absolutePath); System.out.println("absolutePath的根路径为:"+ absolutePath.getRoot()); System.out.println("absolutePath里包含的路径数量:" + absolutePath.getNameCount()); System.out.println(absolutePath.getName(3)); Path path2 = Paths.get("g:","xx","ll"); System.out.println(path2); } }
输出为
path里包含的路径数量:1 path的根路径:null E:\app\talkroom2\WhhTalkRoom_server\. absolutePath的根路径为:E:\ absolutePath里包含的路径数量:4 . g:\xx\ll Process finished with exit code 0
getNameCount()方法返回Path路径所包含的路径名的数量。
接下来的例子展示Files工具类的用法,这个工具类高度封装了文件的各种操作,极其强大。
package NIOTest; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; public class FilesTest { public static void main(String[] args) { try { Path path = Files.copy(Paths.get("./src/main/java/NIOTest/FilesTest.java"), Paths.get("a.txt")); System.out.println(path.toString()); System.out.println("FilesTest.java是否为隐藏问件:" + Files.isHidden(Paths.get("./src/main/java/NIOTest/FilesTest.java"))); //一次性读取FilesTest.java的所有行 List<String> lines = Files.readAllLines(Paths.get("./src/main/java/NIOTest/FilesTest.java"), Charset.forName("UTF-8")); System.out.println(lines); //判断指定文件大小 System.out.println("FilesTest.java的大小为:" + Files.size(Paths.get("./src/main/java/NIOTest/FilesTest.java"))); List<String> poem = new ArrayList<>(); poem.add("水晶潭底银鱼跃"); poem.add("清徐风中碧竿横"); Files.write(Paths.get("poem.txt"), poem, Charset.forName("UTF-8")); //java8进一步增强了Files工具类的功能,允许开发者使用StreamAPI来操作文件目录和文件内容 } catch (IOException ioe) { ioe.printStackTrace(); } } }
输出
a.txt FilesTest.java是否为隐藏问件:false [package NIOTest;, , import java.io.File;, import java.io.IOException;, import java.nio.charset.Charset;, import java.nio.file.Files;, import java.nio.file.Path;, import java.nio.file.Paths;, import java.util.ArrayList;, import java.util.List;, , public class FilesTest {, public static void main(String[] args) {, try {, Path path = Files.copy(Paths.get("./src/main/java/NIOTest/FilesTest.java"), Paths.get("a.txt"));, System.out.println(path.toString());, System.out.println("FilesTest.java是否为隐藏问件:" + Files.isHidden(Paths.get("./src/main/java/NIOTest/FilesTest.java")));, //一次性读取FilesTest.java的所有行, List<String> lines = Files.readAllLines(Paths.get("./src/main/java/NIOTest/FilesTest.java"), Charset.forName("UTF-8"));, System.out.println(lines);, //判断指定文件大小, System.out.println("FilesTest.java的大小为:" + Files.size(Paths.get("./src/main/java/NIOTest/FilesTest.java")));, List<String> poem = new ArrayList<>();, poem.add("水晶潭底银鱼跃");, poem.add("清徐风中碧竿横");, Files.write(Paths.get("poem.txt"), poem, Charset.forName("UTF-8"));, , //java8进一步增强了Files工具类的功能,允许开发者使用StreamAPI来操作文件目录和文件内容, } catch (IOException ioe) {, ioe.printStackTrace();, }, }, }] FilesTest.java的大小为:1496 Process finished with exit code
关于StreamAPI,请移步这里:Java 8 中的 Streams API 详解
二、使用FileVisitor遍历文件和目录
Files工具类提供了如下两个房啊来遍历文件和子目录
walkFileTree(Path start,FileVisitor<? super Path> vistor) :遍历start路径下的所有文件和子目录
walkFileTree(Path start , Set<FileVisitOption> options, int maxDepth, FileVisitor<? super Path> visitor): 上一个方法的重载方法
,最多遍历maxDepth深度的文件。
上面两个方法需要的FileVisitor接口的实例是一个文件访问器,walkFileTree()方法会自动遍历start路径下的文件和子目录,遍历每一个文件和子目录都会调用FileVisitor
中相应的方法。
package NIOTest; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; public class FileVisitorTest { public static void main(String[] args) throws IOException{ Files.walkFileTree(Paths.get(".").toAbsolutePath(),new SimpleFileVisitor<Path>(){ //访问文件时触发 @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("正在访问"+file+"文件"); if(file.endsWith("FileVisitorTest.java")){ System.out.println("---已找到目标文件---"); return FileVisitResult.TERMINATE; } return FileVisitResult.CONTINUE; } //访问目录时触发 @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("正在访问:"+ dir +"路径"); return FileVisitResult.CONTINUE; } }); } }
三、使用WatchService监控文件变化
在之前的java版本中若要监控文件变化则需要启动一个后台线程,写一个定时任务来检查文件是否改变。
Path类提供了如下一个方法来监听文件系统的变化
register(WathcService watcher,WatchEvent.Kind<?>...events)用watcher监听该path代表的目录下的文件变化,events参数指定要监听哪些类型的变化。
看程序
package NIOTest; import org.apache.xmlbeans.impl.store.Path; import java.io.IOException; import java.nio.file.*; public class WatchServiceTest { public static void main(String[] args) throws Exception{ //WatchService代表一个文件系统监听服务,获取文件系统的WatchService对象 WatchService watchService = FileSystems.getDefault().newWatchService(); //调用Path提供的register为该目录注册文件监听服务和监听事件 Paths.get("C:/").register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); //使用一个死循环来重复获取文件变化 while (true){ //获取下一个文件变化事件 WatchKey key = watchService.take(); for (WatchEvent<?> event : key.pollEvents()) { System.out.println(event.context() + "文件发生了"+ event.kind() + "事件"); } //重设WatchKey boolean valid = key.reset(); //重设失败退出监听 if(!valid){ break; } } } }
在获取文件变化事件时有三种方法:
四、访问文件属性
java.nio.file.attribute包下提供大量工具类来读取、修改文件属性,用到的时候再查阅。