10
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

javaのNIO.2おさらい

Last updated at Posted at 2017-11-11

javaのIO,NIOに続いて、NIO.2についておさらい!!

IO : https://qiita.com/liguofeng29/items/e08dc21b16c0057f601e
NIO : https://qiita.com/liguofeng29/items/c827af3d62f219e17755

NIO.2とは

簡単に言えば、既存のNIOを改善したものです。

  1. FileIOを強化した
  2. 非同期Channleに基づくIOを強化した

FileIO強化

コアAPI

API名 概要
Path プラットフォームへ依存しない経路を表す
Paths Pathのユーティルクラス
(Pathインスタンス取得用(get)メソッドのみだった)
Files Fileのユーティルクラス

雑談:Paths,Filesはjavaの一貫した命名ルールに従ったものですね。

  • Paths, Pathのユーティルクラス
  • Files, Fileのユーティルクラス__と言いながら引数が殆どPathだった!!__
  • Arrays, Arrayのユーティルクラス
  • Collections, Collectionのユーティルクラス
  • Objects, Objectのユーティルクラス

Path, Paths

Pathサンプル(markdownで取得したかった)
private static void showPath(Path path) {
    System.out.println("|取得内容|結果|");
    System.out.println("|---|---|");
    System.out.printf("|%s | %s |\r\n", "要素数", path.getNameCount());
    System.out.printf("|%s | %s |\r\n", "指定要素名", path.getName(0));
    System.out.printf("|%s | %s |\r\n", "ファイル名", path.getFileName());
    System.out.printf("|%s | %s |\r\n", "ファイルシステム名", path.getFileSystem());
    System.out.printf("|%s | %s |\r\n", "親", path.getParent());
    System.out.printf("|%s | %s |\r\n", "ルート", path.getRoot());
    System.out.printf("|%s | %s |\r\n", "絶対パスか", path.isAbsolute());
}
Path,Paths
private static void path_test() {
    // 相対パス
    Path relativePath = Paths.get(".", "NIO2", "sub", "nio2-file.txt");
    System.out.println("---- 相対パス ----");
    showPath(relativePath);
    // 絶対パス
    System.out.println("---- 絶対パス ----");
    showPath(relativePath.toAbsolutePath());
}
  • 相対パス
取得内容 結果
要素数 4
指定要素名 .
ファイル名 nio2-file.txt
ファイルシステム名 sun.nio.fs.WindowsFileSystem@6e0be858
.\NIO2\sub
ルート null
絶対パスか false
  • 絶対パス
取得内容 結果
要素数 8
指定要素名 workspace
ファイル名 nio2-file.txt
ファイルシステム名 sun.nio.fs.WindowsFileSystem@6e0be858
C:\workspace\git\java-projects\java-sample.\NIO2\sub
ルート C:\
絶対パスか true
  1. 絶対パス、相対パスによって取得する結果が異なる
  2. sun.nio.fs.WindowsFileSystem、これによって__「プラットフォームへ依存しない」__を実現しているのね?
  3. Paths#getからPathインスタンス取得する(File to Path, Path to Fileもできるが)

Files

Filesサンプル

nio2-src.txt
1行目、AIC
2行目、UTF-8?
3行目
Filesサンプル(markdownで取得したかった)
private static void testFiles(Path path) {
    System.out.println("|取得内容|結果|");
    System.out.println("|---|---|");
    try {
        System.out.printf("|%s | %s |\r\n", "ディレクトリか", Files.isDirectory(path));
        System.out.printf("|%s | %s |\r\n", "隠しか", Files.isHidden(path));
        System.out.printf("|%s | %s |\r\n", "ディレクトリか", Files.isWritable(path));
        System.out.printf("|%s | %s |\r\n", "サイズは", Files.size(path));
        System.out.printf("|%s | " , "ファイル内容取得");
        Files.lines(path).forEach(line -> {
            System.out.printf("%s<br>" , line);
        });
        System.out.printf("|\r\n");
        System.out.printf("|%s | " , "ディレクトリ要素取得");
        Files.list(path.getParent()).forEach(p -> {
            System.out.printf("%s<br>" , p);
        });
        System.out.printf("|\r\n");
        System.out.printf("|%s | %s |\r\n", "ストレジ容量", Files.getFileStore(path).getTotalSpace() / 1024 / 1024 / 1024 + "GB");
        System.out.printf("|%s | %s |\r\n", "利用可能容量", Files.getFileStore(path).getUsableSpace() / 1024 / 1024 / 1024 + "GB");
        System.out.printf("|%s | %s |\r\n", "未割当て容量", Files.getFileStore(path).getUnallocatedSpace() / 1024 / 1024 / 1024 + "GB");
        System.out.printf("|%s | %s |\r\n", "存在するか", Files.exists(path));
        Files.delete(path);
        System.out.printf("|%s | %s |\r\n", "削除する", "削除した");
        System.out.printf("|%s | %s |\r\n", "存在するか", Files.exists(path));
    } catch (IOException e) {
        e.printStackTrace();
    }
}
取得内容 結果
ディレクトリか false
隠しか false
ディレクトリか true
サイズは 64
ファイル内容取得 1行目、AIC
2行目、UTF-8?
3行目
ディレクトリ要素取得 .\NIO2\nio2-desc.txt
.\NIO2\nio2-src.txt
.\NIO2\sub
ストレジ容量 111GB
利用可能容量 54GB
未割当て容量 54GB
存在するか true
削除する 削除した
存在するか false

File#WalkTree

既存IOでは、再帰的な走査を自分で実装する必要があり、コードが複雑&使い勝手がよくなかった。

1.7では、Files#walkFileTreeで再帰的走査が可能になる。

callback 概要
preVisitDirectory ディレクトリアクセス前発生
visitFile ディレクトリアクセス前発生
visitFileFailed ディレクトリアクセス前発生
postVisitDirectory ディレクトリアクセス後発生
FileVisitResult 概要
CONTINUE 継続する
SKIP_SIBLINGS 継続後、該当file,directoryの兄弟階層は走査しない
SKIP_SUBTREE 継続後、該当file,directoryの子供階層は走査しない
TERMINATE walk(走査)を終了する

walkFileTreeのサンプルはあっちこっち在ったので、割愛!

Files#walk

1.8では、Files#walkが便利!

Files.walk
Files.walk(Paths.get(".", "NIO2"), FileVisitOption.FOLLOW_LINKS)
    // directoryとfile入れ替え
    .sorted(Comparator.reverseOrder())
    // 削除対象確認
    .peek(System.out::println)
    // 削除
    .forEach(path -> {
        try {
            Files.delete(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });

ほか

WatchService

File変更を監視する仕組みである。
従来のやり方で、考えられる実装は

  1. 別スレッドを立ち上げて
  2. 状態を保存して
  3. 一定間隔で走査して前の状態と比較する

WatchServiceを使えばファイルが簡単にできる。

WatchServiceサンプル
try {
    WatchService watchService = FileSystems.getDefault().newWatchService();
    Paths.get(".").register(
        watchService,
        StandardWatchEventKinds.ENTRY_CREATE, // CREATE監視
        StandardWatchEventKinds.ENTRY_DELETE, // DELETE監視
        StandardWatchEventKinds.ENTRY_MODIFY  // MODIFY監視
    );
    System.out.println("-----watch開始-----");
    while (true) {
        // 待ち続ける
        WatchKey key = watchService.take();
        key.pollEvents().stream()
            .forEach(
                watchEvent -> {
                    System.out.println("発生種類 : " + watchEvent.kind().name());
                    System.out.println("対象名  : " + watchEvent.context());
                });
        // 次の監視
        if (!key.reset()) {
            break;
        }
    }
} catch (IOException | InterruptedException e) {
    e.printStackTrace();
}
  1. WatchServiceを生成する
  2. WatchServiceを登録し、監視内容も登録する
  3. WatchKey取得
    • take() : WatchKey取得するまで待ち続ける
    • poll() : WatchKey取得し、なければnull
    • poll(long timeout, TimeUnit unit):timeout分待ち続ける
  4. 処理
  5. WatchKeyリセット

属性読み書き

ざっくり、FileAttributeViewを実装したもので、細かい属性を操作できるそうです。

  • AclFileAttributeView
  • BasicFileAttributeView
  • DocFileAttributeView
  • FileOnwerFileAttributeView
  • PosixFileFileAttributeView
  • UserDefinedFileAttributeView
BasicFileAttributeViewサンプル
Path path = Paths.get(".", "NIO2", "nio2-src.txt");

BasicFileAttributeView view = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes attributes = view.readAttributes();

System.out.println("前回アクセス : " + attributes.lastAccessTime());
System.out.println("最新修正時刻 : " + attributes.lastModifiedTime());
10
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?