Created
November 8, 2014 20:18
-
-
Save fge/35acf87ab7f166765540 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.github.fge; | |
| import java.io.Closeable; | |
| import java.io.IOException; | |
| import java.nio.file.FileVisitResult; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| import java.nio.file.SimpleFileVisitor; | |
| import java.nio.file.attribute.BasicFileAttributes; | |
| import java.util.Iterator; | |
| import java.util.NoSuchElementException; | |
| import java.util.concurrent.ArrayBlockingQueue; | |
| import java.util.concurrent.BlockingQueue; | |
| import java.util.concurrent.ExecutorService; | |
| import java.util.concurrent.Executors; | |
| import java.util.concurrent.TimeUnit; | |
| public final class LazyDirectoryIterator | |
| implements Iterator<Path>, Closeable | |
| { | |
| private static final int QUEUE_SIZE = 5; | |
| private static final long TIMEOUT_QUANTITY = 100L; | |
| private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS; | |
| private final ExecutorService executor | |
| = Executors.newSingleThreadExecutor(); | |
| private final BlockingQueue<Path> queue | |
| = new ArrayBlockingQueue<>(QUEUE_SIZE); | |
| private volatile Path nextPath; | |
| private boolean needNext = true; | |
| public LazyDirectoryIterator(final Path baseDir) | |
| { | |
| executor.submit(new Runnable() | |
| { | |
| @Override | |
| public void run() | |
| { | |
| try { | |
| Files.walkFileTree(baseDir, new CustomVisitor()); | |
| } catch (IOException ignored) { | |
| Thread.currentThread().interrupt(); | |
| } | |
| } | |
| }); | |
| } | |
| @Override | |
| public boolean hasNext() | |
| { | |
| try { | |
| if (needNext) { | |
| nextPath = queue.poll(TIMEOUT_QUANTITY, TIMEOUT_UNIT); | |
| needNext = false; | |
| } | |
| return nextPath != null; | |
| } catch (InterruptedException ignored) { | |
| Thread.currentThread().interrupt(); | |
| return false; | |
| } | |
| } | |
| @Override | |
| public Path next() | |
| { | |
| if (!hasNext()) | |
| throw new NoSuchElementException(); | |
| needNext = true; | |
| return nextPath; | |
| } | |
| @Override | |
| public void remove() | |
| { | |
| throw new UnsupportedOperationException(); | |
| } | |
| @Override | |
| public void close() | |
| throws IOException | |
| { | |
| executor.shutdownNow(); | |
| } | |
| private final class CustomVisitor | |
| extends SimpleFileVisitor<Path> | |
| { | |
| @Override | |
| public FileVisitResult preVisitDirectory(final Path dir, | |
| final BasicFileAttributes attrs) | |
| throws IOException | |
| { | |
| try { | |
| queue.put(dir); | |
| return FileVisitResult.CONTINUE; | |
| } catch (InterruptedException e) { | |
| Thread.currentThread().interrupt(); | |
| throw new IOException("timeout", e); | |
| } | |
| } | |
| } | |
| public static void main(final String... args) | |
| throws IOException | |
| { | |
| final Path baseDir = Paths.get("/home/fge/t"); | |
| try ( | |
| final LazyDirectoryIterator it = new LazyDirectoryIterator(baseDir) | |
| ) { | |
| while (it.hasNext()) | |
| System.out.println(it.next()); | |
| } | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment