Spec-Zone .ru
спецификации, руководства, описания, API
|
Вы должны создать приложение, которое рекурсивно посетит все файлы в дереве файла? Возможно, Вы должны удалить каждый .class
файл в дереве, или находят каждый файл, к которому не получили доступ в прошлом году. Можно сделать так с FileVisitor
интерфейс.
Этот раздел покрывает следующее:
Чтобы обойти дерево файла, Вы сначала должны реализовать a FileVisitor
. A FileVisitor
определяет необходимое поведение в ключевых пунктах в процессе обхода: когда файл посещают, прежде, чем к каталогу получают доступ, после того, как к каталогу получают доступ, или когда отказ происходит. У интерфейса есть четыре метода, которые соответствуют этим ситуациям:
preVisitDirectory
postVisitDirectory
visitFile
BasicFileAttributes
передается к методу, или можно использовать пакет DosFileAttributeView
определить, есть ли у файла "скрытый" набор битов.visitFileFailed
– Вызванный, когда к файлу нельзя получить доступ. Определенное исключение передают к методу. Можно выбрать, выдать ли исключение, напечатать это к консоли или файлу журнала и так далее.Если Вы не должны реализовать все четыре из FileVisitor
методы, вместо того, чтобы реализовать FileVisitor
интерфейс, можно расшириться SimpleFileVisitor
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
метод позволяет Вам дополнительно определить предел на числе уровней, которые посещают и ряд FileVisitOption
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
.
пример показывает, как сделать это.Copy
Если Вы пишете поиск файла, Вы выполняете сравнение в 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; }
Следующие примеры демонстрируют механизм обхода файла:
Find
– Рекурсивно вызывает поиск дерева файла файлов и каталогов, которые соответствуют определенный образец шарика. Этот пример обсуждается в Обнаружении Файлов.Chmod
– Рекурсивно полномочия изменений на дереве файла (для систем POSIX только).Copy
– Рекурсивно копирует дерево файла.WatchDir
– Демонстрирует механизм, который наблюдает каталог за файлами, которые были созданы, удалены или изменены. Вызов этой программы с -r
опция наблюдает все дерево за изменениями. Для получения дополнительной информации о службе уведомления о файле, см. Наблюдение Каталога для Изменений.