(Java)搜索特定文件的计算机(更快的方式)

时间:2014-11-13 05:47:09

标签: java search

static boolean fileFound;
static String fileName = "tumblr.txt";
public static void searchFile(File f)     //File f is "C:\\"
{  
   try
   {
    if(f.isDirectory())
    {
    File [] fi = f.listFiles();
    for(int i=0;i<fi.length;i++)
    {
    if(fileFound==true) 
    {
      break;
    }  
    System.out.println(fi[i].getName());
    searchFile(fi[i]);
    }
    }
    else
    {
    if(f.getName().equalsIgnoreCase(fileName) ||  f.getName().toLowerCase().startsWith(fileName.toLowerCase()))||(f.getName().toLowerCase().endsWith(fileName.toLowerCase())))
    {    
    System.out.print("file found " + f.getAbsolutePath()); 
    fileFound=true;
    }
    }
   }
    catch(Exception e)
      {
      }
 }

这是我搜索名为tumblr.txt的文本文件的代码,或者它可以是我计算机上的任何文件类型。上面的代码有效,但它确实很慢。花了2分钟才找到我桌面上的文件。有没有办法以更快的搜索速度做到这一点?就像“开始”菜单的“搜索程序和文件”功能一样。如果您愿意,可以为我提供链接。

1 个答案:

答案 0 :(得分:2)

如果您使用多个线程,则可以更快地执行搜索。

我发布这个类的一个例子,它使用一个线程池来扫描目录,另一个线程检查名称与这些目录中包含的文件的匹配。 这两类线程与两个阻塞队列连接,一个用于搜索目录,另一个用于匹配的文件。找到文件后,扫描目录的线程将以毒丸结束。有一个AtomicLong变量来跟踪正在进行的目录计数。

在我的笔记本电脑中,它或多或少地在120秒内扫描整个高清。 我希望这会有所帮助。

    import java.io.File;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.atomic.AtomicLong;

    public class FindFile {

        private static final File   POISONPILL  = new File("");

        private static class RunnableDirSearch implements Runnable {
            private final BlockingQueue<File>   dirQueue;
            private final BlockingQueue<File>   fileQueue;
            private final AtomicLong            count;
            private final int                   num;

            public RunnableDirSearch(final BlockingQueue<File> dirQueue, final BlockingQueue<File> fileQueue, final AtomicLong count, final int num) {
                this.dirQueue = dirQueue;
                this.fileQueue = fileQueue;
                this.count = count;
                this.num = num;
            }

            @Override
            public void run() {
                try {
                    File dir = dirQueue.take();
                    while (dir != POISONPILL) {
                        final File[] fi = dir.listFiles();
                        if (fi != null) {
                            for (final File element : fi) {
                                if (element.isDirectory()) {
                                    count.incrementAndGet();
                                    dirQueue.put(element);
                                } else {
                                    fileQueue.put(element);
                                }
                            }
                        }
                        final long c = count.decrementAndGet();
                        if (c == 0) {
                            end();
                        }
                        dir = dirQueue.take();
                    }
                } catch (final InterruptedException ie) {
                    // file found or error
                }
            }

            private final void end() {
                try {
                    fileQueue.put(POISONPILL);
                } catch (final InterruptedException e) {
                    // empty
                }
                for (int i = 0; i < num; i++) {
                    try {
                        dirQueue.put(POISONPILL);
                    } catch (final InterruptedException e) {
                        // empty
                    }
                }
            }
        }

        private static class CallableFileSearch implements Callable<File> {
            private final BlockingQueue<File>   dirQueue;
            private final BlockingQueue<File>   fileQueue;
            private final String                name;
            private final int                   num;

            public CallableFileSearch(final BlockingQueue<File> dirQueue, final BlockingQueue<File> fileQueue, final String name, final int num) {
                this.dirQueue = dirQueue;
                this.fileQueue = fileQueue;
                this.name = name;
                this.num = num;
            }

            @Override
            public File call() throws Exception {
                File file = fileQueue.take();
                while (file != POISONPILL) {
                    final String filename = file.getName().toLowerCase();
                    final String lf = name.toLowerCase();
                    if (filename.equalsIgnoreCase(name) || filename.startsWith(lf) || filename.endsWith(lf)) {
                        end();
                        return file;
                    }
                    file = fileQueue.take();
                }
                return null;
            }

            private final void end() {
                for (int i = 0; i < num; i++) {
                    try {
                        dirQueue.put(POISONPILL);
                    } catch (final InterruptedException e) {
                        // empty
                    }
                }
            }
        }

        private final String        filename;
        private final File          baseDir;
        private final int           concurrency;
        private final AtomicLong    count;

        public FindFile(final String filename, final File baseDir, final int concurrency) {
            this.filename = filename;
            this.baseDir = baseDir;
            this.concurrency = concurrency;
            count = new AtomicLong(0);
        }

        public File find() {
            final ExecutorService ex = Executors.newFixedThreadPool(concurrency + 1);
            final BlockingQueue<File> dirQueue = new LinkedBlockingQueue<File>();
            final BlockingQueue<File> fileQueue = new LinkedBlockingQueue<File>(10000);
            for (int i = 0; i < concurrency; i++) {
                ex.submit(new RunnableDirSearch(dirQueue, fileQueue, count, concurrency));
            }
            count.incrementAndGet();
            dirQueue.add(baseDir);
            final Future<File> c = ex.submit(new CallableFileSearch(dirQueue, fileQueue, filename, concurrency));
            try {
                final File f = c.get();
                return f;
            } catch (final Exception e) {
                return null;
            } finally {
                ex.shutdownNow();
            }
        }

        public static void main(final String[] args) {
            final String filename = "test.h2.db23";
            final File baseDir = new File("C:/");
            final FindFile ff = new FindFile(filename, baseDir, 6);
            final long ini = System.currentTimeMillis();
            final File f = ff.find();
            final long end = System.currentTimeMillis();
            System.out.println(f + " " + (end - ini) + " ms");
        }
    }