带有FileVisitor类和walkFileTree()的Swingworker,它在内部遍历目录树中的“一组”文件;在哪里发布()?

时间:2013-11-18 23:46:05

标签: java publish swingworker filevisitor

似乎应该在如下的类中定义长时间运行的树步行器任务:

  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;
  }

我可以将walkFileTree()调用的所有4个方法放在doInBackground()内的内部类中,但这似乎是一厢情愿的想法。

P.S。我无法使用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分钟)

这是我的处理方法。 println没有执行。

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

... zzzzzzzzzzzzzzzzzzzzz ............

3 个答案:

答案 0 :(得分:1)

由于您的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返回等待工作者完成只是作为一个例子

答案 1 :(得分:0)

由于@Madprogrammer没有使用GUI而DID使用get()[直到doInBackground()执行完成后才进行WAITS],我添加了一个GUI,修改了他的publish(),并包含了对done()的调用,就像锦上添花一样。我自己的树木行走者还没有工作,但是Mad's向我展示了道路。以下是新的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);
      }

答案 2 :(得分:0)

并不是我放弃了SwingWorker,我只是确定我不知道对线程的蹲坐并决定对此做些什么。过去两天我用一个更简单的项目取得了成功,这使我将相同的策略应用于我的(各种)Treewalker(项目),现在: (1)将输出附加到textarea时不要使屏幕闪烁 (2)用按钮按钮优雅地立即结束。

所有这一切都是为“后台”FileVisitor任务使用单独的线程(而不是SwingWorker),其中: (a)让GUI保持“负责”,从而能够无缝接受输出,并提供一个按钮供用户按下以中止和 (b)使代码看起来很容易理解。

所以@Mad,谢谢你的帮助。 (自11月19日以来,我一直没有专注于这个!我很沮丧,我刚离开它,成功做了其他事情,并且勇敢地回来再试一次)。

P.S。我发现文本 Ivar Horton的Beginning 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;
  }                                      
}