2
2

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]過去の自分が作成した機能をjava.io.FileからNIO.2で書き直し

Last updated at Posted at 2018-11-24

背景

Javaでファイルやディレクトリ操作をしたいと思った場合、お世話になるクラスは以下が一般的かと思います。

  • java.io.File
  • java.nio.Path
  • java.nio.Files
  • java.nio.file.Paths

Fileクラスは昔からあります。
NIO.2は、Java 7で導入されたクラスで、Fileクラスに比べて新しいです。

なので、新規で実装する場合は、NIO.2を使用したいものです。

今回は、自分がjava.io.Fileで書いたコードを、NIO.2で書き直したものを紹介します。

紹介する機能

  • 指定されたディレクトリ内にファイルが存在するか
  • 指定されたディレクトリを中身も含めて全削除

指定されたディレクトリ内にファイルが存在するか

java 6以前

import java.io.File;

public class Demo {
    public static void main(String[] args) {
        File file = new File("C:/temp/");

        // ファイル名の一覧を取得し、存在チェック
        if (file.listFiles().length == 0) {
            System.out.println("ファイルはありません。");
        } else {
            System.out.println("ファイルがあります。");
        }
    }
}

File.listFiles()の戻り値は、File型の配列で返されます。
そのlenghで配列の長さを見て、判定するという流れです。

java 7以降

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Demo {
    public static void main(String[] args) {
        Path path = Paths.get("C:/temp/");

        try {
            if (Files.list(path).findAny().isPresent()) {
                System.out.println("ファイルはあります。");
            } else {
                System.out.println("ファイルはありません。");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Files.list は、ディレクトリ内のエントリを取得してStremで返します。
findAny() は、最初に見つけた要素をOptionalで返します。
isPresent() は、Optionalが保持する値がnullならばfalse、nullじゃなかったらtrueを返します。

指定されたディレクトリを中身も含めて全削除

java 6以前

import java.io.File;

public class Demo {
    public static void main(String[] args) {
        File dir = new File("C:/temp/");
        deleteDir(dir);
    }

    public static void deleteDir(File dir) {
        if (dir.exists() && dir.isDirectory()) {
            for (File child : dir.listFiles()) {
                if (child.isDirectory()) {
                    deleteDir(child);
                } else {
                    child.delete();
                }
            }
        }
        dir.delete();
    }
}

java 8以降

注意! Streamを使用しているので、java8以降でしか動作しません。

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;

public class Demo {
    public static void main(String[] args) {
        Path path = Paths.get("C:/temp/");

        // ディレクトリを全削除
        try {
            Files.walk(path).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
            path.toFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Files.walk(path) で、IOExceptionが発生する可能性があるので、throwするかcatchで対応してください。
Files.walk(path) は、サブディレクトリを含む一覧を取得しています。
sorted(Comparator.reverseOrder()) は、降順に並び替えます。
こうすると、ファイルが先頭にきて、ディレクトリは後ろのほうに並び替えられます。
そして、filterして抽出したPaths型をFiles型に変換し、ループで削除…ということをしています。
(ごめんなさい。うまく説明できていないかもしれません。)

下記のようにすれば、Stream<Path>List<Path> に変換することができます。
.collect(Collectors.toList()) を追加するだけですが…

List<Path> list = Files.walk(path).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
for (Path p : list) {
    System.out.println(p);
}

おまけ

試行錯誤していたら、たまたまできた機能です。
せっかくなので、紹介します。

指定されたディレクトリ内のファイル削除

java 8以降

注意! Streamを使用しているので、java8以降でしか動作しません。

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Demo {
    public static void main(String[] args) {
        Path path = Paths.get("C:/temp/");

        // ディレクトリ内にあるファイルを削除(サブディレクトリは削除しない)
        try {
            Files.walk(path).filter(Files::isRegularFile).map(Path::toFile).forEach(File::delete);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

.filter(Files::isRegularFile) で、通常ファイルかどうかをチェックしています。
これでディレクトリは削除対象から除外されます。

最後に

いまだにJava 8のラムダ式、Stream、Optionalなどに慣れないです。
時代遅れ感がすごいので、なんとかしたい。けど調べれば調べるほど分からなくなって沼にハマっていきます…

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?