Почему я сталкиваюсь с DirectoryNotEmptyException при рекурсивном удалении каталога?

#java #io #java-7 #nio

#java #io #java-7 #nio

Вопрос:

У меня есть некоторый код, который должен рекурсивно удалять каталог, используя пакет java.nio. Код был в основном скопирован из http://www.adam-bien.com/roller/abien/entry/java_7_deleting_recursively_a , и выглядит следующим образом:

 public class NotEmptyDirDemo {
    public static void main(String[] pArgs) throws Exception {
        final Path path = Paths.get("d:/tmp/woda");
        Assert.assertTrue(Files.isDirectory(path));
        new NotEmptyDirDemo().removeDir(path);
        Assert.assertFalse(Files.isDirectory(path));
    }

    protected void removeDir(Path pDir) throws IOException {
        final FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path pDir,
                             BasicFileAttributes pAttrs) throws IOException {
                return super.preVisitDirectory(pDir, pAttrs);
            }

            @Override
            public FileVisitResult postVisitDirectory(Path pDir, IOException pExc) throws IOException {
                final FileVisitResult res = super.postVisitDirectory(pDir, pExc);
                Files.delete(pDir);
                return res;
            }

            @Override
            public FileVisitResult visitFile(Path pFile, BasicFileAttributes pAttrs) throws IOException {
                if (!Files.isWritable(pFile)) {
                    pFile.toFile().setWritable(true);
                }
                Files.delete(pFile);
                return super.visitFile(pFile, pAttrs);
            }
        };
        Files.walkFileTree(pDir, fv);
    }
}
  

Теперь я могу представить, что при выполнении этого материала происходят все плохие вещи (например, отсутствуют разрешения на удаление и тому подобное. Как бы то ни было, это меня удивляет:

 Exception in thread "main" java.nio.file.DirectoryNotEmptyException:
     d:tmpwodawodawork
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:266)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1126)
at com.foo.demo.NotEmptyDirDemo$1.postVisitDirectory(NotEmptyDirDemo.java:32)
at com.foo.demo.NotEmptyDirDemo$1.postVisitDirectory(NotEmptyDirDemo.java:1)
at java.nio.file.Files.walkFileTree(Files.java:2688)
at java.nio.file.Files.walkFileTree(Files.java:2742)
at com.foo.demo.NotEmptyDirDemo.removeDir(NotEmptyDirDemo.java:45)
at com.foo.demo.NotEmptyDirDemo.main(NotEmptyDirDemo.java:18)
  

Средство обхода каталогов выполняет итерацию по дереву каталогов. Если он находит каталог, он выполняет итерацию по нему и, наконец, удаляет его (в postVisitDirectory). Если он находит файл, он тоже удаляется (в visitFile).

Итак, каталог, который удаляется, всегда должен быть пустым. Однако это не так.

Любое разумное объяснение?

Спасибо,

Jochen

Комментарии:

1. Просто размышляю, но я думаю, что вполне возможно, что есть файл, который по какой-то причине не подлежит удалению, но Files . удаление не вызывает исключения, поэтому файл все еще существует, когда вы пытаетесь удалить каталог

2. FileVisitor определяет четыре метода. Попытка реализовать четвертый метод и поместить в него инструкцию print; это может показать, какие файлы, если таковые имеются, не удалось посетить.