|
Spec-Zone .ru
спецификации, руководства, описания, API
|
Вы должны создать приложение, которое рекурсивно посетит все файлы в дереве файла? Возможно, Вы должны удалить каждый .class файл в дереве, или находят каждый файл, к которому не получили доступ в прошлом году. Можно сделать так с FileVisitor интерфейс.
Этот раздел покрывает следующее:
Чтобы обойти дерево файла, Вы сначала должны реализовать a FileVisitor. A FileVisitor определяет необходимое поведение в ключевых пунктах в процессе обхода: когда файл посещают, прежде, чем к каталогу получают доступ, после того, как к каталогу получают доступ, или когда отказ происходит. У интерфейса есть четыре метода, которые соответствуют этим ситуациям:
BasicFileAttributes передается к методу, или можно использовать пакет visitFileFailed – Вызванный, когда к файлу нельзя получить доступ. Определенное исключение передают к методу. Можно выбрать, выдать ли исключение, напечатать это к консоли или файлу журнала и так далее.Если Вы не должны реализовать все четыре из FileVisitor методы, вместо того, чтобы реализовать FileVisitor интерфейс, можно расшириться class. Этот class, который реализует FileVisitor интерфейс, посещает все файлы в дереве и бросает IOError когда с ошибкой встречаются. Можно расширить этот class и переопределить только методы, которых Вы требуете.
Вот пример, который расширяется SimpleFileVisitor напечатать все записи в дереве файла. Это печатает запись, является ли запись регулярным файлом, символьной ссылкой, каталогом, или некоторым другим "неуказанным" типом файла. Это также печатает размер, в байтах, каждого файла. Любое исключение, с которым встречаются, печатается к консоли.
FileVisitor методы показывают полужирным:
import static java.nio.file.FileVisitResult.*;
public static class PrintFiles
extends SimpleFileVisitor<Path> {
// Print information about
// each type of file.
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr) {
if (attr.isSymbolicLink()) {
System.out.format("Symbolic link: %s ", file);
} else if (attr.isRegularFile()) {
System.out.format("Regular file: %s ", file);
} else {
System.out.format("Other: %s ", file);
}
System.out.println("(" + attr.size() + "bytes)");
return CONTINUE;
}
// Print each directory visited.
@Override
public FileVisitResult postVisitDirectory(Path dir,
IOException exc) {
System.out.format("Directory: %s%n", dir);
return CONTINUE;
}
// If there is some error accessing
// the file, let the user know.
// If you don't override this method
// and an error occurs, an IOException
// is thrown.
@Override
public FileVisitResult visitFileFailed(Path file,
IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
Как только Вы реализовали Ваш FileVisitor, как Вы инициируете обход файла? Есть два walkFileTree методы в Files class.
Первый метод требует только начальной точки и экземпляра Вашего FileVisitor. Можно вызвать PrintFiles посетитель файла следующим образом:
Path startingDir = ...; PrintFiles pf = new PrintFiles(); Files.walkFileTree(startingDir, pf);
Второе walkFileTree метод позволяет Вам дополнительно определить предел на числе уровней, которые посещают и ряд перечисления. Если Вы хотите гарантировать, что этот метод обходит все дерево файла, можно определить Integer.MAX_VALUE для максимального параметра глубины.
Можно определить FileVisitOption перечисление, FOLLOW_LINKS, который указывает, что символьные ссылки должны сопровождаться.
Этот фрагмент кода показывает, как метод с четырьмя параметрами может быть вызван:
import static java.nio.file.FileVisitResult.*; Path startingDir = ...; EnumSet<FileVisitOption> opts = EnumSet.of(FOLLOW_LINKS); Finder finder = new Finder(pattern); Files.walkFileTree(startingDir, opts, Integer.MAX_VALUE, finder);
Дерево файла является обойденной глубиной сначала, но невозможно заставить предположения об итерации упорядочить это, подкаталоги посещают.
Если Ваша программа будет изменять файловую систему, Вы должны тщательно рассмотреть, как Вы реализуете Ваш FileVisitor.
Например, если Вы пишете, что рекурсивное удаляет, Вы сначала удаляете файлы в каталоге прежде, чем удалить каталог непосредственно. В этом случае Вы удаляете каталог в postVisitDirectory.
Если Вы пишете рекурсивную копию, Вы создаете новый каталог в preVisitDirectory прежде, чем попытаться скопировать файлы в это (в visitFiles). Если Вы хотите сохранить атрибуты исходного каталога (подобный UNIX cp -p команда), Вы должны сделать это после того, как файлы были скопированы, в postVisitDirectory.
Если Вы пишете поиск файла, Вы выполняете сравнение в visitFile метод. Этот метод находит все файлы, которые соответствуют Ваши критерии, но он не находит каталоги. Если Вы хотите найти и файлы и каталоги, следует также выполнить сравнение в любом preVisitDirectory или postVisitDirectory метод. пример показывает, как сделать это.Find
Вы должны решить, хотите ли Вы, чтобы символьные ссылки сопровождались. Если Вы удаляете файлы, например, после символьных ссылок не могло бы быть желательным. Если Вы копируете дерево файла, Вы могли бы хотеть позволить его. По умолчанию, walkFileTree не следует за символьными ссылками.
visitFile метод вызывается для файлов. Если Вы определили FOLLOW_LINKS у опции и Вашего дерева файла есть круговая ссылка к родительскому каталогу, о каталоге цикличного выполнения сообщают в visitFileFailed метод с FileSystemLoopException. Следующий фрагмент кода показывает, как поймать круговую ссылку и от пример:Copy
@Override
public FileVisitResult
visitFileFailed(Path file,
IOException exc) {
if (exc instanceof FileSystemLoopException) {
System.err.println("cycle detected: " + file);
} else {
System.err.format("Unable to copy:" + " %s: %s%n", file, exc);
}
return CONTINUE;
}
Этот случай может произойти только, когда программа следует за символьными ссылками.
Возможно, Вы хотите обойти поиск дерева файла определенного каталога и, когда найдено, Вы хотите, чтобы процесс завершился. Возможно, Вы хотите пропустить определенные каталоги.
FileVisitor методы возвращают a FileVisitResult значение. Можно прервать процесс обхода файла или управлять, посещают ли каталог значения, которые Вы возвращаете в FileVisitor методы:
CONTINUE – Указывает, что обход файла должен продолжаться. Если preVisitDirectory возвраты метода CONTINUE, каталог посещают.TERMINATE – Сразу прерывает обход файла. Никакие дальнейшие методы обхода файла не вызываются после того, как это значение возвращается.SKIP_SUBTREE – Когда preVisitDirectory возвраты это значение, указанный каталог и его подкаталоги пропускаются. Это ответвление "сокращается" дерева.SKIP_SIBLINGS – Когда preVisitDirectory возвраты это значение, указанный каталог не посещают, postVisitDirectory не вызывается, и не далее непосещаемые одноуровневые элементы посещают. Если возвращено из postVisitDirectory метод, никакие дальнейшие одноуровневые элементы не посещают. По существу ничто далее не происходит в указанном каталоге.В этом фрагменте кода называют любой каталог SCCS пропускается:
import static java.nio.file.FileVisitResult.*;
public FileVisitResult
preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
(if (dir.getFileName().toString().equals("SCCS")) {
return SKIP_SUBTREE;
}
return CONTINUE;
}
В этом фрагменте кода, как только определенный файл располагается, имя файла печатается к стандартному выводу, и обход файла завершается:
import static java.nio.file.FileVisitResult.*;
// The file we are looking for.
Path lookingFor = ...;
public FileVisitResult
visitFile(Path file,
BasicFileAttributes attr) {
if (file.getFileName().equals(lookingFor)) {
System.out.println("Located file: " + file);
return TERMINATE;
}
return CONTINUE;
}
Следующие примеры демонстрируют механизм обхода файла:
Chmod – Рекурсивно полномочия изменений на дереве файла (для систем POSIX только).Copy – Рекурсивно копирует дерево файла.WatchDir – Демонстрирует механизм, который наблюдает каталог за файлами, которые были созданы, удалены или изменены. Вызов этой программы с -r опция наблюдает все дерево за изменениями. Для получения дополнительной информации о службе уведомления о файле, см. Наблюдение Каталога для Изменений.