0

I'm not sure if I'm using the right approach so I'm open to new ideas before telling me that i'm doing it wrong. I have an array of directories path that I need to look for files. Let's say all .txt at example. Now I run a Files.walkFileTree(...) on every directory and with the SimpleFileVisitor that stops at first match. But now i want to add a next button that keeps searching from the point I stop. How can I do this?

I've thought that I could save all matches on a array and then read it from there but it's space and memory consuming. So a better idea would be appreciate.

// example paths content: [/usr, /etc/init.d, /home]
ArrayList<String> paths; 
for( String s : paths )
    Files.walkFileTree(Paths.get(s), new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            if (alreadyfound >= 10) {
                return FileVisitResult.TERMINATE;
            }
            if (file.toString().endsWith(".txt")) {
                System.out.println("Found: " + file.toFile());
            }
            return FileVisitResult.CONTINUE;
        }
    });
Praveen Kumar K S
  • 3,024
  • 1
  • 24
  • 31
Umuril Lyerood
  • 175
  • 1
  • 1
  • 9
  • can't you simply save the i point in session? – DamienB Aug 17 '16 at 12:51
  • @DamienBoue Yeah, but I don't know how. If let's say I look in root, and finds something on /home/file.txt. I can save the path but how can I continue on all the root subdirectories missing? – Umuril Lyerood Aug 17 '16 at 12:54
  • You said you have an array. Get the index in the Array of the matched path. And then put it in session. Then you can start at this index in our Array. Disolay code for more help – DamienB Aug 17 '16 at 12:59
  • @DamienBoue I've added a simplified version of what i've already written. – Umuril Lyerood Aug 17 '16 at 13:11
  • I have a tricky solution for you. Remove the forceach and use a "normal" for to loop into yours paths. Visit your files and when found what you have to found save the file name in sessions and the index of the loop. Then when you click on next start the loop at the index and exclude the previous file you have saved in session. If you have multiple match into same path save into an array and verify if file exist in the array – DamienB Aug 17 '16 at 13:24
  • @DamienBoue that's a possible solution too, but in the extreme case of adding only root it wouldn't have any improvement. But keeping away this particular case it's a good solution. Add it as an answer for others to read too. Meanwhile I'll think what solution suits better for me – Umuril Lyerood Aug 17 '16 at 13:39

1 Answers1

1

I once wrote a class that should do exactly what you described. I solved it by running the FileVisitor in its own Thread. When a file was found with a desired extension it simply stopped execution with wait() until a button signaled to continue with notify().

public class FileSearcher extends Thread{
    private Object lock = new Object();
    private Path path;
    private JLabel label;
    private String extension;

    public FileSearcher(Path p, String e, JLabel l){
        path = p;
        label = l;
        extension = e;
    }       
    public void findNext(){
        synchronized(lock){
            lock.notify();
        }   
    }   
    @Override
    public void run() {
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    if(file.toString().toLowerCase().endsWith(extension)){
                        label.setText(file.toString());
                        synchronized(lock){
                            try {
                                lock.wait();
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            }
                        }
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }
}

A simple example how to use it would be this

JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JLabel label = new JLabel();
FileSearcher fileSearcher = new FileSearcher(Paths.get("c:\\bla"), ".txt", label);
JButton button = new JButton();
button.setText("next");
button.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent arg0) {
        fileSearcher.findNext();
    }});
panel.add(label);
panel.add(button);
frame.add(panel);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
fileSearcher.start();
ArcticLord
  • 3,999
  • 3
  • 27
  • 47
  • I don't know very much about java concurrency (?). So I don't really understand what this code does. I'll try it and read documentation before using it but seems that's what I was looking for. Just one thing, how can I change it to read a group? I mean instead of calling findNext twice that It finds two file in one call. (Just the idea, don't need to change the code if you want) – Umuril Lyerood Aug 17 '16 at 14:08
  • Add a counter and increment for every found file. And if bigger than some value do reset counter and do the `lock.wait` call (in its `synchronized` block of course) – ArcticLord Aug 17 '16 at 14:14