【问题标题】:ignore exception and continue & counting files in a directory忽略异常并继续计数目录中的文件
【发布时间】:2015-12-01 11:17:27
【问题描述】:

下面的sn-p代码统计一个目录下的文件个数:

      Path path = ...;
       ....
      long count = 0;
        try {
           count  = Files.walk(path).parallel().filter(p -> !Files.isDirectory(p)).count();

        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }

以上代码获取文件数失败,如果抛出异常。

问题是:如何忽略异常,继续统计文件数。

在 Java 7 中:我使用了 Files.walkFileTree(path, utils),具有以下类:

 public class Utils extends SimpleFileVisitor<Path> {

    private long count;

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        if (attrs.isRegularFile()) {
            count++;

        }
        return CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
        System.err.println(file.getFileName());
        return CONTINUE;
    }

    public long countFilesInDirectoryJava7() {
        return count;
    }

}

编辑:这是异常的堆栈跟踪:

  Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException: E:\8431c36f5b6a3d7169de9cc70a\1025
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:88)
    at java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:104)
    at java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1784)
    at java.util.stream.AbstractTask.compute(AbstractTask.java:297)
    at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:401)
    at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734)
    at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
    at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
    at Utils.countFilesInDirectoryJava8(Utils.java:47)
    at TestPath.main(TestPath.java:27)
Caused by: java.nio.file.AccessDeniedException: E:\8431c36f5b6a3d7169de9cc70a\1025
    at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
    at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
    at sun.nio.fs.WindowsDirectoryStream.<init>(WindowsDirectoryStream.java:86)
    at sun.nio.fs.WindowsFileSystemProvider.newDirectoryStream(WindowsFileSystemProvider.java:518)
    at java.nio.file.Files.newDirectoryStream(Files.java:457)
    at java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:300)
    at java.nio.file.FileTreeWalker.next(FileTreeWalker.java:372)
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:84)
    ... 13 more
Java Result: 1

【问题讨论】:

  • 异常的堆栈跟踪是什么?
  • @JBNizet 我用异常的堆栈跟踪更新了问题。
  • 除此之外,我认为您对此无能为力。继续使用 SimpleFileVisitor。
  • 我担心这确实是不可能的。您可以轻松地修改重新实现 Files.walk() 以忽略异常,但不幸的是,他们将 FileTreeIterator 和相关类包设为私有,因此您最终将自己重写整个 walk 算法。
  • 顺便说一下,要数的时候不要用.mapToLong(j -&gt; 1).sum()。只需使用…………count()

标签: java-8 java-stream


【解决方案1】:

到目前为止,Files.walk 似乎仍然不能很好地处理流。相反,您可能想改用Files.newDirectoryStream。这里有一些代码 sn-p 可能会有所帮助。

    static class FN<T extends Path> implements Function<T, Stream<T>> {
    @Override
    public Stream<T> apply(T p) {
        if (!Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)) {
            return Stream.of(p);
        } else {
            try {
                return toStream(Files.newDirectoryStream(p)).flatMap(q -> apply((T) q));
            } catch (IOException ex) {
                return Stream.empty();
            }
        }
    }
}

public static void main(String[] args) throws IOException {
    Path path = Paths.get("some path");
    long count = toStream(Files.newDirectoryStream(path))
            .parallel()
            .flatMap(new FN<>()::apply)
            .count();             

    System.out.println("count: " + count);
}

static <T> Stream<T> toStream(Iterable<T> iterable) {
    return StreamSupport.stream(iterable.spliterator(), false);
}

【讨论】:

    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多