Swingworker с классом FileVisitor и walkFileTree(), который выполняет внутреннюю итерацию по "набору" файлов в дереве каталогов; где опубликовать ()?

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

  public class TreeWalker extends SwingWorker<Void,String> implements FileVisitor<Path>

И началось где-то так:

TreeWalker walker = (new TreeWalker());
           walker.execute();

Долгосрочная задача не только инициируется, но и полностью выполняется одним вызовом walkFileTree()метод в Files учебный класс. Так что, конечно, вызов должен быть в doInBackGround(),

  protected Void doInBackground() throws Exception {
    Files.walkFileTree(SearchyGUI.p , this);
    return null;
  }

Обратите внимание, что walkTreeFile() внутренне вызывает четыре метода для каждого найденного файла. Написанный программистом цикл неосуществим. Так что есть моя проблема. Как я использую publish() отправить информацию о файле в виде строки process метод мне нужно переопределить? Примеры, которые я видел, имеют publish() внутри doInBackground(), но внутри цикла, что здесь невозможно.

Один из четырех методов, которые меня больше всего волнуют, visitFile(), который walkFileTree() должен быть в состоянии найти, и я подозреваю, что это где поставить publish():

  public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException {
    if (...we want this file...) 
        publish(f.toString());
    return CONTINUE;
  }

Я мог бы поместить все 4 метода, которые WalkFileTree() вызывает во внутреннем классе внутри doInBackground(), но это похоже на желаемое за действительное.

PS я не могу использовать get(); в этом весь смысл (насколько я понимаю)- слишком большая задержка в получении результатов (может обработать тысячи файлов, чтобы найти дюжину), чтобы дождаться окончания doInBackground().

==========================================

РЕДАКТИРОВАТЬ #3, 50 минут после первоначального времени публикации

  public static void doIt(){
      try {
        System.out.println("It begins..."); // This does happen.
        TreeWalker walker = new TreeWalker();
        walker.execute(); 
        SearchyGUI.info.setVisible(true); // Form is displayed, stays blank.
      }      
      catch (Exception e) { System.out.println("Uh-oh"); } // This does NOT happen.
    }   

==========================================

(РЕДАКТИРОВАТЬ № 2, 40 минут после публикации)

Вот мой метод обработки. Печать не выполнена.

protected void process(String s) {
    System.out.println("in process()...");
    report(s); // my method to append text area with another line of file info
}

Кроме того, оператор класса, который содержит doInBackground() изменилось:

public class TreeWalker extends SwingWorker<Void, String> implements Runnable{

Walking класс вложен в doInBackground(),

==========================================

(РЕДАКТИРОВАТЬ, через 20 минут после публикации)

Это скомпилировано, но ничего не сделал:

  protected Void doInBackground() throws Exception 
  {
    class Walking implements FileVisitor<Path>
    {  
      @Override
      public FileVisitResult visitFile(Path f, BasicFileAttributes a) throws IOException 
      {
        String modifyDate    = a.lastModifiedTime().toString().substring(0,10);
        String fpathname = f.toString();// + "\\" + f.getFileName().toString());
        if (...we want this one...) 
            publish(f.getFileName());
        return disposition;
      }
... other methods excluded
    } // end inner class    

    System.out.println("walking??");                                 // We get here ...
    Files.walkFileTree(SearchyGUI.p , (FileVisitor<? super Path>) this);
    System.out.println("Finished walking??");                        // ... but not here.
    return null;
  } // end of doInBackground()

=============================

... еще одна чертова правка... мой нынешний класс...

public class GUI extends JFrame implements ActionListener, MouseListener, KeyListener

public class TreeWalker extends SwingWorker<Void, String> implements Runnable{

protected Void doInBackground() throws Exception {
  class Walking implements FileVisitor<Path>{ // CLASS INSIDE doInBackground

... zzzzzzzzzzzzzzzzzzz...........

3 ответа

Решение

Потому что ваш TreeWalker расширяет оба SwingWorker и реализует FileVisitorВы могли бы позвонить publish из любого метода обратного вызова, например...

public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
    publish(dir.toString());
    return FileVisitResult.CONTINUE;
}

Теперь, исходя из ваших потребностей, вам нужно будет преобразовать Path элемент к String используя любой метод, который вам нужен...

Обновлено с рабочим примером

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;

public class TreeWalkerExample {

    public static void main(String[] args) {
        new TreeWalkerExample();
    }

    public TreeWalkerExample() {
        TreeWalker tw = new TreeWalker();
        tw.execute();
        try {
            tw.get();
        } catch (InterruptedException | ExecutionException ex) {
            ex.printStackTrace();
        }
    }

    public class TreeWalker extends SwingWorker<Void, Path> implements FileVisitor<Path> {

        @Override
        protected void process(List<Path> chunks) {
            for (Path p : chunks) {
                System.out.println(p);
            }
        }

        @Override
        protected Void doInBackground() throws Exception {
            Path p = Paths.get(System.getProperty("user.home"));
            System.out.println(p);
            Files.walkFileTree(p, this);
            return null;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            FileVisitResult fvr = FileVisitResult.CONTINUE;
            if (dir.getFileName().toString().startsWith(".")) {
                fvr = FileVisitResult.SKIP_SUBTREE;
            }
            return fvr;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            publish(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            return FileVisitResult.TERMINATE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }
    }

}

Nb, у этого нет GUI с этим, но вместо этого ждет рабочего, чтобы закончить, ожидая get возвращаться только в качестве примера

Так как @Madprogrammer не использовал GUI, а DID использовал get() [который ЖДЕТ, пока не завершится выполнение doInBackground()], я добавил GUI, изменил его publish() и включил вызов done (), просто как обледенение на торте. Мой собственный ходок по дереву еще не работает, но Безумный показал мне путь. Вот основные моменты новой версии Mad-with-GUI.

public class TreeWalkerExample {

  static GUI gui;

  public static void main(String args[]) 
  {...invokelater...
     public void run() { 
       gui = new GUI(); 
       gui.setVisible(true); }
   }

      public TreeWalkerExample() { 
        (new TreeWalker()).execute();  
      }

      public class TreeWalker extends SwingWorker<Void,Path> implements FileVisitor<Path> {

          protected Void doInBackground() throws Exception {
              Path p = Paths.get("C:\\","Users","\\Dave","\\Documents","\\Java");
              gui.appendOutput(p.toString());
              Files.walkFileTree(p, this);
              return null;
          }

          public FileVisitResult visitFile(Path file, BasicFileAttributes a) throws IOException{
              publish(file);
              return FileVisitResult.CONTINUE;
          }

          protected void process(List<Path> chunks) {
              for (Path p : chunks) 
                gui.appendOutput(p.getFileName().toString());
          }

          protected void done(){
              gui.appendOutput("\nDone");
          }
    }
    ===================================================================================================
    public class GUI extends javax.swing.JFrame {

      JTextArea output;

      private void btnWalkMouseClicked(java.awt.event.MouseEvent evt) {                                     
        new TreeWalkerExample();
      }                                    

      public void appendOutput(String s){
        output.append("\n" + s);
      }

Дело не в том, что я отказался от SwingWorker, я просто решил, что не знаю, как сидеть на корточках, и решил что-то с этим сделать. Мой успех в последние 2 дня в гораздо более простом проекте привел меня к применению той же стратегии к моим (различным) Treewalker (проектам), которые теперь: (1) не заставляют мигать экран при добавлении вывода в текстовую область и (2) закончить изящно и немедленно нажатием кнопки.

Все, что для этого потребовалось - использовать отдельный поток (не SwingWorker) для "фона" FileVisitor задача, которая: (а) позволяет графическому интерфейсу оставаться "ответственным" и, таким образом, иметь возможность беспрепятственно принимать вывод, а также предоставляет пользователю кнопку для отмены и (б) делает код более разумным и легким для отслеживания.

Так что @Mad, СНОВА спасибо за помощь. (Я не работаю только над этим с 19 ноября! Я так расстроился, что просто ушел, занялся другими делами и получил смелость вернуться и попробовать снова).

PS Я нашел текст "Начало Java (7)" Ивара Хортона бесценным. Лучшее, что я видел о темах.

FWIW вот схема моей программы резервного копирования:

public class Copy extends Thread{

  public static FileVisitResult disposition = FileVisitResult.CONTINUE;
  static Thread           t ;
  static FilesCopied      output ;   
...
  public static TreeWalker      fv;
...

  public void run() {    
...
    fv             = new TreeWalker();  
    try {
      Files.walkFileTree(UserIO.inputPath,fv);
    }
    catch ...
  }

  public /* inner */ class TreeWalker implements FileVisitor<Path> {
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      maybeCopy(file);
      return disposition;
    }
    public FileVisitResult preVisitDirectory(Path d, BasicFileAttributes a) throws IOException {
      maybeMakeDir(d,fromRootDepth);
      return disposition;     
    }
... 
  } // end TreeWalker

...
  public static void main(String[] args) throws IOException {
    EventQueue.invokeLater(new Runnable()  
      public void run() { gui = new UserIO(); gui.setVisible(true); 
    }});  
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        output = new FilesCopied();
      }});
    t = new Copy();
  }
} // end class Copy
======================
public class UserIO extends JFrame {
...
  public void btnBackupMouseClicked(MouseEvent evt) throws IOException { 
...
      Copy.t.start();
  }

  public void btnStopMouseClicked(MouseEvent evt) throws IOException { 
    Copy.disposition = FileVisitResult.TERMINATE;
  }                                      
}
Другие вопросы по тегам