selecting folder

edited November 2013 in Programming Questions

in my current sketch I use...

void setup() {    
  java.io.File folder = new java.io.File(dataPath(""));             
    java.io.FilenameFilter csvFilter = new java.io.FilenameFilter() {  
    public boolean accept(File dir, String name) {
      return name.toLowerCase().endsWith(".csv");
    }
  };
  filenames = folder.list(csvFilter);         
  ...do the rest of my junk with the filenams array...
}

...which I copied and pasted from an example on processing.org. This is fine and dandy, but I have lots of different data sets I like to view in my sketch, so for now I have to copy and paste the .csv files from different folders into the "data" folder, which is a bit of a pain. So, I ran across this example...

void setup() {
  selectFolder("Select a folder to process:", "folderSelected");
}

void folderSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    println("User selected " + selection.getAbsolutePath());
  }
}

...but I don't know how to merge the two. The .getAbsolutePath() method returns a string. The .csv filter in the first code block isn't happy if the folder variable is a string.

BM

Tagged:

Answers

  • java.io.File folder = new java.io.File(selection.getAbsolutePath());  
    

    ?

  • Thanks, I thought I tried that but I must have messed up the syntax. Ok, this is what I have so far, and I think I'm really close-

    java.io.File folder;
    String[] filenames;
    
    void setup() {
      selectFolder("Select a folder to process:", "folderSelected");
      java.io.FilenameFilter csvFilter = new java.io.FilenameFilter() {  
        public boolean accept(File dir, String name) {
          return name.toLowerCase().endsWith(".csv");
        }
      };
      filenames = folder.list(csvFilter);  
    
        for (int i = 0; i < filenames.length; i++) {
        println(filenames[i]);
      }
    }
    
    void folderSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } 
      else {
        println("User selected " + selection.getAbsolutePath());
        java.io.File folder = new java.io.File(selection.getAbsolutePath());
      }
    }
    

    but now I get a null pointer exception.

  • The folder declared in folderSelected() is local to this function and hides the global variable that remains null.

    Beside, I think selectFolder() returns immediately before getting the user input, so even without the redeclaration, folder will be null.

  • Logic is more like:

    import java.io.*;
    
    File folder;
    String[] filenames;
    FilenameFilter csvFilter = new FilenameFilter() { 
      public boolean accept(File dir, String name) {
        return name.toLowerCase().endsWith(".csv");
      }
    };
    
    void setup() {
      selectFolder("Select a folder to process:", "folderSelected");
    }
    
    void draw() {
      if (folder != null) { // User selected something, at least!
        filenames = folder.list(csvFilter); 
        for (int i = 0; i < filenames.length; i++) {
          println(filenames[i]);
        }
        folder = null;
      }
    }
    
    void folderSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } else {
        println("User selected " + selection.getAbsolutePath());
        folder = new File(selection.getAbsolutePath());
      }
    }
    
  • I can't thank you enough for your help, but I still have an issue here. I really need the for loop inside of setup(). I read the data (thousands of lines, from a dozen or so .csv files) and do a lot of stuff with it in setup(). I generate a couple of arrayLists of the tables of data, do calculations, etc., and then pass all of that on to draw() to plot it. Your code works fine, but if I put the if statement and for loop in setup, it no longer works.

    import java.io.*;
    
    File folder;
    String[] filenames;
    FilenameFilter csvFilter = new FilenameFilter() {
      public boolean accept(File dir, String name) {
        return name.toLowerCase().endsWith(".csv");
      }
    };
    
    void setup() {
      selectFolder("Select a folder to process:", "folderSelected");
      if (folder != null) { // User selected something, at least!
        filenames = folder.list(csvFilter);
        for (int i = 0; i < filenames.length; i++) {
          println(filenames[i]);
        }
        folder = null;
      }
    }
    
    void draw() {
    //  if (folder != null) { // User selected something, at least!
    //    filenames = folder.list(csvFilter);
    //    for (int i = 0; i < filenames.length; i++) {
    //      println(filenames[i]);
    //    }
    //    folder = null;
    //  }
    }
    
    void folderSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } 
      else {
        println("User selected " + selection.getAbsolutePath());
        folder = new File(selection.getAbsolutePath());
      }
    }
    
  • Re-read again my message: selectFolder() returns immediately, so folder isn't usable there.

    The idea behind my code is to process the folder only once. But indeed, draw() can start before that. You can had logic to handle that, or do it in another way:

    Another way to do that:

    import java.io.*;
    
    FilenameFilter csvFilter = new FilenameFilter() {
      public boolean accept(File dir, String name) {
        return name.toLowerCase().endsWith(".csv");
      }
    };
    
    void setup() {
      selectFolder("Select a folder to process:", "folderSelected");
      noLoop(); // Don't start draw()
    }
    
    void draw() {
      background(100);
      text(frameCount, 10, height / 2);
    }
    
    void folderSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } else {
        println("User selected " + selection.getAbsolutePath());
        processFolder(selection.getAbsolutePath());
        loop(); // Resume draw()
      }
    }
    
    void processFolder(String path) {
      File folder = new File(path);
      String[] filenames = folder.list(csvFilter);
      for (int i = 0; i < filenames.length; i++) {
        println(filenames[i]);
        // Load the files, process them, etc. here
      }
    }
    

    Beware: draw() is called once before being stopped. You can check like:

    if (frameCount <= 1) return;
    

    at the start of draw() to ensure all data is loaded before it runs.

  • edited November 2013

    How about this 1? :-?
    Remember that selectFolder() runs in a separate Thread!!! So we gotta delay() for it! b-(

    void setup() {
      method("waitForFolder");
      //thread("waitForFolder");
    }
    
    void waitForFolder() {
      folder = null;
    
      selectFolder("Select a folder to process:", "folderSelected");
      while (folder == null)   delay(200);
    
      for (String csv: filenames = folder.list(csvFilter))   println(csv);
    }
    
  • Yeah, I'm starting to understand it now. I'd really like to try to avoid making a massive change to my code. Right now this project of mine isn't even on my official work list so I squeeze it in as I have time, and to be honest, I've been spending far more time on it than I should. As it is now, I hide my processing windows whenever my boss walks by...

    But I will try those other solutions here in the next day or so.

    Thanks...

Sign In or Register to comment.