[JAVA] Code de démonstration qui recherche récursivement les répertoires avec Files.walkFileTree

Aperçu

Le processus de recherche récursive dans les répertoires en Java peut être facilement implémenté en utilisant la méthode Files.walkFileTree introduite dans Java 1.7. Utilisez également une classe qui implémente l'interface FileVisitor pour effectuer un traitement arbitraire sur chaque fichier ou répertoire recherché.

walkFileTree

Passez le chemin d'accès qui est le point de départ de la recherche dans le premier argument start et passez l'instance FileVisitor dans le deuxième argument.

walkFileTree


public static Path walkFileTree(Path start, FileVisitor<? super Path> visitor) throws IOException {
  // ...
}

environnement

référence

Code de démonstration pour le traitement récursif

Dans ce code de démonstration, les chemins relatifs (à partir du chemin de départ) des fichiers et répertoires sous le chemin de départ à rechercher sont acquis et rassemblés dans une liste. Dans le cas d'un fichier, MD5 calcule la somme de contrôle.

ComputeFileChecksumVisitor

La classe SimpleFileVisitor est une classe de visiteur de base qui implémente l'interface FileVisitor. Héritez de cette classe pour implémenter le traitement des fichiers et des répertoires.

Opérations sur les fichiers

Le visitFile remplacé est une méthode qui est rappelée pour chaque fichier recherché, et ici, elle implémente le processus d'obtention du chemin relatif du fichier et de calcul de la somme de contrôle.

Opérations sur les répertoires

La méthode preVisitDirectory est une méthode qui est rappelée pour chaque répertoire recherché. La somme de contrôle n'étant pas calculée dans le répertoire, seul le chemin relatif est acquis. En outre, il existe également une méthode appelée postVisitDirectory pour les opérations sur les répertoires, mais le moment auquel elle est rappelée est différente car le nom de la méthode a pre, post. ..

code

ComputeFileChecksumVisitor


import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

public class ComputeFileChecksumVisitor extends SimpleFileVisitor<Path> {

	private final Path start;
	private final String hashAlg;
	private final List<FileItem> items = new ArrayList<>();

	public ComputeFileChecksumVisitor(Path start, String hashAlg) {
		this.start = start;
		this.hashAlg = hashAlg;
	}

	public List<FileItem> getResult() {
		return items;
	}

	@Override
	public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
		if (!dir.equals(start)) {
			FileItem item = new FileItem(relativePath(dir), "");
			items.add(item);
		}
		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
		FileItem item = new FileItem(relativePath(file), checksum(file));
		items.add(item);
		return FileVisitResult.CONTINUE;
	}

	private Path relativePath(Path path) {
		if (path.startsWith(start)) {
			return path.subpath(start.getNameCount(), path.getNameCount());
		}
		throw new RuntimeException();
	}

	private String checksum(Path path) throws IOException {
		MessageDigest digest = null;
		try {
			digest = MessageDigest.getInstance(hashAlg);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		try (InputStream input = Files.newInputStream(path);
			 DigestInputStream dInput = new DigestInputStream(input, digest)) {
			while (dInput.read() != -1) {}
		}
		return toHex(digest.digest());
	}

	private String toHex(byte[] bytes) {
		StringBuilder builder = new StringBuilder(bytes.length * 2);
		for (byte b : bytes) {
			builder.append(String.format("%02x", b));
			//builder.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
		}
		return builder.toString();
	}

}

FileItem

ComputeFileChecksum Cette classe stocke des informations sur les fichiers et répertoires recherchés par Visiteur. Le champ path stocke le chemin relatif (à partir du chemin d'origine) du fichier ou du répertoire recherché. Le champ checksum stocke la somme de contrôle du fichier recherché, ou un caractère vide dans le cas d'un répertoire.

code

FileItem


import java.nio.file.Path;

public class FileItem implements Comparable<FileItem> {
	private Path path;
	private String checksum;

	public FileItem(Path path, String checksum) {
		this.path = path;
		this.checksum = checksum;
	}

	public Path getPath() {
		return path;
	}
	public String getChecksum() {
		return checksum;
	}

	@Override
	public int compareTo(FileItem o) {
		return this.compareTo(o);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((checksum == null) ? 0 : checksum.hashCode());
		result = prime * result + ((path == null) ? 0 : path.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		FileItem other = (FileItem) obj;
		if (checksum == null) {
			if (other.checksum != null)
				return false;
		} else if (!checksum.equals(other.checksum))
			return false;
		if (path == null) {
			if (other.path != null)
				return false;
		} else if (!path.equals(other.path))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "FileItem [path=" + path + ", checksum=" + checksum + "]";
	}

}

démo

J'ai créé les répertoires dir1 et dir2 avec la même structure de répertoires que celle indiquée ci-dessous. Le nom de fichier et le contenu du fichier sont identiques, mais les horodatages de la date et de l'heure de création sont différents. Recherchez ces dir1 et dir2 dans le code de démonstration respectivement pour obtenir une liste de fichiers, répertoires et une somme de contrôle des fichiers pour vérifier s'ils ont la même structure.

D:var
├─dir1
│  │  test1.txt
│  │  test2.txt
│  │
│  ├─aaa
│  │  └─ddd
│  ├─bbb
│  │      test3.txt
│  │
│  └─ccc
│          test4.txt
│
└─dir2
    │  test1.txt
    │  test2.txt
    │
    ├─aaa
    │  └─ddd
    ├─bbb
    │      test3.txt
    │
    └─ccc
            test4.txt

Exécuter

Demo


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

public class Demo {

	public static void main(String[] args) throws Exception {

		Path dir1 = Paths.get("D:", "var", "dir1");
		ComputeFileChecksumVisitor dir1Visit = new ComputeFileChecksumVisitor(dir1, "MD5");
		Files.walkFileTree(dir1, dir1Visit);

		Path dir2 = Paths.get("D:", "var", "dir2");
		ComputeFileChecksumVisitor dir2Visit = new ComputeFileChecksumVisitor(dir2, "MD5");
		Files.walkFileTree(dir2, dir2Visit);

		List<FileItem> dir1Files = dir1Visit.getResult();
		System.out.println("Root : " + dir1.toString());
		dir1Files.forEach(System.out::println);

		List<FileItem> dir2Files = dir2Visit.getResult();
		System.out.println("Root : " + dir2.toString());
		dir2Files.forEach(System.out::println);

		if (dir1Files.equals(dir2Files)) {
			System.out.println("equal");
		} else {
			System.out.println("not equal");
		}
	}

}

Résultat de l'exécution

Root : D:\var\dir1
FileItem [path=aaa, hash=]
FileItem [path=aaa\ddd, hash=]
FileItem [path=bbb, hash=]
FileItem [path=bbb\test3.txt, hash=ed6e956a3d549303751e3238ab04bb46]
FileItem [path=ccc, hash=]
FileItem [path=ccc\test4.txt, hash=2c97af7af48689fc67a2700d9f051af6]
FileItem [path=test1.txt, hash=ac6a2aaa9317ef1f007c092c6a5fd75e]
FileItem [path=test2.txt, hash=811ad90a8dafc585bb64b23b6200969e]
Root : D:\var\dir2
FileItem [path=aaa, hash=]
FileItem [path=aaa\ddd, hash=]
FileItem [path=bbb, hash=]
FileItem [path=bbb\test3.txt, hash=ed6e956a3d549303751e3238ab04bb46]
FileItem [path=ccc, hash=]
FileItem [path=ccc\test4.txt, hash=2c97af7af48689fc67a2700d9f051af6]
FileItem [path=test1.txt, hash=ac6a2aaa9317ef1f007c092c6a5fd75e]
FileItem [path=test2.txt, hash=811ad90a8dafc585bb64b23b6200969e]
equal

Recommended Posts

Code de démonstration qui recherche récursivement les répertoires avec Files.walkFileTree
Exemple de code pour appeler l'API Yahoo! Local Search en Java
Comment implémenter la fonctionnalité de recherche dans Rails
Exemple de code pour appeler l'API Yahoo! Shopping Product Search (v3) avec Spring RestTemplate
Comment colorer la sortie de la console de code dans Eclipse
Code pour échapper aux chaînes JSON en Java
Méthode de recherche
Comment implémenter UICollectionView avec du code uniquement dans Swift
Exemple de code pour convertir List en List <String> dans Java Stream
Paramètres de sortie vers la console de débogage dans Visual Studio Code
Comment afficher un aperçu du navigateur avec VS Code
Comment écrire une recherche de comparaison de dates dans Rails