Java 7引入的NIO.2(java.nio.file)大幅简化了文件操作。本文讲解Path、Files、WatchService、内存映射文件等高级用法。
一、Path与Files
java
复制
下载
import java.nio.file.*; Path path = Path.of("/tmp/data.txt"); // 或 Paths.get("/tmp/data.txt") System.out.println(path.getFileName()); System.out.println(path.getParent()); System.out.println(path.toAbsolutePath()); // 文件操作 Files.exists(path); Files.createFile(Path.of("/tmp/new.txt")); Files.createDirectories(Path.of("/tmp/a/b/c")); Files.deleteIfExists(path); // 读写 Files.writeString(path, "hello"); String content = Files.readString(path); List<String> lines = Files.readAllLines(path); Files.write(path, List.of("line1", "line2"), StandardOpenOption.APPEND); // 复制、移动 Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING); Files.move(src, dest, StandardCopyOption.ATOMIC_MOVE); // 遍历目录 try (Stream<Path> stream = Files.walk(Path.of("/tmp"), 2)) { stream.filter(Files::isRegularFile) .forEach(System.out::println); } // 查找 try (Stream<Path> stream = Files.find(Path.of("/tmp"), Integer.MAX_VALUE, (p, attr) -> p.toString().endsWith(".log"))) { stream.forEach(System.out::println); }二、读取大文件
java
复制
下载
// 逐行读取,内存友好 try (BufferedReader reader = Files.newBufferedReader(path)) { String line; while ((line = reader.readLine()) != null) { process(line); } } // 流式读取 try (Stream<String> lines = Files.lines(path)) { lines.filter(s -> s.contains("ERROR")) .forEach(System.out::println); }三、内存映射文件
MappedByteBuffer将文件映射到内存,读写速度接近内存。
java
复制
下载
public class MappedFileReader { public static void main(String[] args) throws IOException { Path path = Path.of("large.dat"); try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)) { long size = channel.size(); MappedByteBuffer buffer = channel.map( FileChannel.MapMode.READ_ONLY, 0, size); byte[] data = new byte[1024]; while (buffer.hasRemaining()) { int len = Math.min(buffer.remaining(), data.length); buffer.get(data, 0, len); process(data, len); } } } }写入:
java
复制
下载
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) { MappedByteBuffer buffer = channel.map( FileChannel.MapMode.READ_WRITE, 0, 1024 * 1024); buffer.put("hello".getBytes()); buffer.force(); // 刷盘 }四、文件锁
java
复制
下载
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE)) { FileLock lock = channel.tryLock(); if (lock != null) { try { // 独占写 } finally { lock.release(); } } }五、WatchService监控目录
java
复制
下载
WatchService watchService = FileSystems.getDefault().newWatchService(); Path dir = Path.of("/tmp/watched"); dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); while (true) { WatchKey key = watchService.take(); for (WatchEvent<?> event : key.pollEvents()) { System.out.println(event.kind() + ": " + event.context()); } key.reset(); }六、异步I/O
java
复制
下载
AsynchronousFileChannel channel = AsynchronousFileChannel.open( path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { attachment.flip(); System.out.println(new String(attachment.array(), 0, result)); } @Override public void failed(Throwable exc, ByteBuffer attachment) { exc.printStackTrace(); } });七、实战:日志文件分析器
java
复制
下载
public class LogAnalyzer { public static Map<String, Long> countByLevel(Path logFile) throws IOException { try (Stream<String> lines = Files.lines(logFile)) { return lines .filter(l -> l.contains("ERROR") || l.contains("WARN") || l.contains("INFO")) .map(l -> { if (l.contains("ERROR")) return "ERROR"; if (l.contains("WARN")) return "WARN"; return "INFO"; }) .collect(Collectors.groupingBy(s -> s, Collectors.counting())); } } public static void main(String[] args) throws IOException { Map<String, Long> stats = countByLevel(Path.of("app.log")); stats.forEach((k, v) -> System.out.println(k + ": " + v)); } }八、总结
NIO.2让文件操作更简洁。内存映射适合大文件随机访问,WatchService适合目录监控,异步I/O适合高并发场景。记住用try-with-resources管理资源。