ファイルI/O(NIO.2)
ファイルI/O(NIO.2)
Section titled “ファイルI/O(NIO.2)”Java 7で導入されたNIO.2(java.nio.fileパッケージ)は、ファイル操作を効率的に行うためのAPIです。この章では、NIO.2の使い方について詳しく解説します。
Pathインターフェース
Section titled “Pathインターフェース”Pathは、ファイルシステム内のパスを表すインターフェースです。
import java.nio.file.Path;import java.nio.file.Paths;
// Pathの作成Path path1 = Paths.get("/home/user/documents/file.txt");Path path2 = Paths.get("C:", "Users", "user", "documents", "file.txt");Path path3 = Paths.get(".", "src", "main", "java");
// 相対パスと絶対パスPath absolutePath = path1.toAbsolutePath();Path normalizedPath = path1.normalize();
// パスの結合Path base = Paths.get("/home/user");Path file = base.resolve("documents/file.txt");Path parent = file.getParent();Path fileName = file.getFileName();Path root = file.getRoot();
// パスの情報取得boolean isAbsolute = path1.isAbsolute();int nameCount = path1.getNameCount();Path name = path1.getName(0);
// パスの比較boolean equals = path1.equals(path2);int compare = path1.compareTo(path2);boolean startsWith = path1.startsWith("/home");boolean endsWith = path1.endsWith("file.txt");Filesクラス
Section titled “Filesクラス”Filesクラスは、ファイル操作のための静的メソッドを提供します。
ファイルの読み書き
Section titled “ファイルの読み書き”import java.nio.file.Files;import java.nio.file.Paths;import java.nio.charset.StandardCharsets;import java.util.List;
// ファイルの読み込みPath filePath = Paths.get("file.txt");
// すべての行を読み込みList<String> lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
// すべてのバイトを読み込みbyte[] bytes = Files.readAllBytes(filePath);
// ストリームとして読み込みtry (Stream<String> stream = Files.lines(filePath, StandardCharsets.UTF_8)) { stream.forEach(System.out::println);}
// ファイルの書き込みString content = "Hello, World!";Files.write(filePath, content.getBytes(StandardCharsets.UTF_8));
// 行のリストを書き込みList<String> linesToWrite = Arrays.asList("Line 1", "Line 2", "Line 3");Files.write(filePath, linesToWrite, StandardCharsets.UTF_8);
// 追記モードで書き込みFiles.write(filePath, "New line".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);ファイルの作成と削除
Section titled “ファイルの作成と削除”// ファイルの作成Path newFile = Paths.get("newfile.txt");Files.createFile(newFile);
// ディレクトリの作成Path newDir = Paths.get("newdir");Files.createDirectory(newDir);
// 複数階層のディレクトリを作成Path nestedDir = Paths.get("parent/child/grandchild");Files.createDirectories(nestedDir);
// ファイルの削除Files.delete(newFile);
// ファイルが存在する場合のみ削除Files.deleteIfExists(newFile);
// ディレクトリの削除(空の場合のみ)Files.delete(newDir);ファイルのコピーと移動
Section titled “ファイルのコピーと移動”Path source = Paths.get("source.txt");Path target = Paths.get("target.txt");
// ファイルのコピーFiles.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
// ディレクトリのコピー(再帰的)Path sourceDir = Paths.get("sourcedir");Path targetDir = Paths.get("targetdir");Files.walk(sourceDir).forEach(sourcePath -> { Path targetPath = targetDir.resolve(sourceDir.relativize(sourcePath)); try { Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { e.printStackTrace(); }});
// ファイルの移動(リネーム)Path oldPath = Paths.get("oldname.txt");Path newPath = Paths.get("newname.txt");Files.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING);ファイル属性の取得
Section titled “ファイル属性の取得”// ファイルの存在確認boolean exists = Files.exists(filePath);
// ファイルの種類確認boolean isRegularFile = Files.isRegularFile(filePath);boolean isDirectory = Files.isDirectory(filePath);boolean isSymbolicLink = Files.isSymbolicLink(filePath);
// ファイルのサイズlong size = Files.size(filePath);
// ファイルの権限確認boolean isReadable = Files.isReadable(filePath);boolean isWritable = Files.isWritable(filePath);boolean isExecutable = Files.isExecutable(filePath);
// 最終更新日時FileTime lastModified = Files.getLastModifiedTime(filePath);Instant instant = lastModified.toInstant();
// 所有者情報(POSIXファイルシステム)UserPrincipal owner = Files.getOwner(filePath);System.out.println("Owner: " + owner.getName());ファイル属性の設定
Section titled “ファイル属性の設定”// 最終更新日時を設定FileTime newTime = FileTime.from(Instant.now());Files.setLastModifiedTime(filePath, newTime);
// 所有者を設定UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();UserPrincipal newOwner = lookupService.lookupPrincipalByName("username");Files.setOwner(filePath, newOwner);
// ファイル権限を設定(POSIX)Set<PosixFilePermission> permissions = EnumSet.of( PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.GROUP_READ, PosixFilePermission.OTHERS_READ);Files.setPosixFilePermissions(filePath, permissions);ディレクトリの走査
Section titled “ディレクトリの走査”Files.walk()
Section titled “Files.walk()”// ディレクトリツリーを再帰的に走査Path root = Paths.get("/home/user/documents");
try (Stream<Path> stream = Files.walk(root)) { stream.filter(Files::isRegularFile) .forEach(System.out::println);}
// 最大深度を指定try (Stream<Path> stream = Files.walk(root, 2)) { stream.forEach(System.out::println);}Files.list()
Section titled “Files.list()”// ディレクトリの直接の子要素のみを取得Path dir = Paths.get("/home/user/documents");
try (Stream<Path> stream = Files.list(dir)) { stream.filter(Files::isDirectory) .forEach(System.out::println);}Files.find()
Section titled “Files.find()”// 条件に合うファイルを検索Path root = Paths.get("/home/user/documents");
BiPredicate<Path, BasicFileAttributes> matcher = (path, attrs) -> { return attrs.isRegularFile() && path.getFileName().toString().endsWith(".txt");};
try (Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, matcher)) { stream.forEach(System.out::println);}FileVisitorインターフェース
Section titled “FileVisitorインターフェース”ディレクトリツリーを走査する際のカスタム動作を定義できます。
import java.nio.file.FileVisitResult;import java.nio.file.SimpleFileVisitor;import java.nio.file.attribute.BasicFileAttributes;
public class MyFileVisitor extends SimpleFileVisitor<Path> {
@Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { System.out.println("Visiting file: " + file); return FileVisitResult.CONTINUE; }
@Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { System.out.println("Entering directory: " + dir); return FileVisitResult.CONTINUE; }
@Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { System.out.println("Leaving directory: " + dir); return FileVisitResult.CONTINUE; }
@Override public FileVisitResult visitFileFailed(Path file, IOException exc) { System.err.println("Failed to visit: " + file); return FileVisitResult.CONTINUE; }}
// 使用例Path root = Paths.get("/home/user/documents");Files.walkFileTree(root, new MyFileVisitor());WatchService
Section titled “WatchService”ファイルシステムの変更を監視するサービスです。
import java.nio.file.WatchService;import java.nio.file.WatchKey;import java.nio.file.WatchEvent;import java.nio.file.StandardWatchEventKinds;
Path dir = Paths.get("/home/user/documents");WatchService watchService = FileSystems.getDefault().newWatchService();
// 監視するイベントを登録WatchKey key = dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
// イベントを監視while (true) { WatchKey watchKey = watchService.take();
for (WatchEvent<?> event : watchKey.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); Path fileName = (Path) event.context();
if (kind == StandardWatchEventKinds.ENTRY_CREATE) { System.out.println("File created: " + fileName); } else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { System.out.println("File deleted: " + fileName); } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { System.out.println("File modified: " + fileName); } }
boolean valid = watchKey.reset(); if (!valid) { break; }}ファイル検索ユーティリティ
Section titled “ファイル検索ユーティリティ”public class FileSearchUtil {
public static List<Path> findFiles(Path root, String extension) throws IOException { List<Path> results = new ArrayList<>();
Files.walkFileTree(root, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (file.getFileName().toString().endsWith(extension)) { results.add(file); } return FileVisitResult.CONTINUE; } });
return results; }
public static long getTotalSize(Path directory) throws IOException { AtomicLong totalSize = new AtomicLong();
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { totalSize.addAndGet(attrs.size()); return FileVisitResult.CONTINUE; } });
return totalSize.get(); }}NIO.2のポイント:
- Path: ファイルシステム内のパスを表す
- Files: ファイル操作の静的メソッド
- ファイルの読み書き: readAllLines、write、linesなど
- ディレクトリの走査: walk、list、find
- FileVisitor: カスタム走査動作の定義
- WatchService: ファイルシステムの変更監視
NIO.2を使用することで、効率的で柔軟なファイル操作が可能です。