java - (Java) 在计算机中搜索特定文件(更快的方法)

标签 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 分钟才在我的桌面上找到该文件。有没有办法以更快的搜索速度做到这一点?就像开始菜单的“搜索程序和文件”功能一样。如果需要,您可以向我提供链接。

最佳答案

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

我为此类发布了一个示例,它使用一个线程池来扫描目录,并使用另一个线程来检查名称与这些目录中包含的文件的匹配情况。 这两类线程与两个阻塞队列连接,一个用于要搜索的目录,另一个用于要匹配的文件。当找到该文件时,扫描目录的线程将收到信号以毒丸结束。有一个 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");
        }
    }

关于java - (Java) 在计算机中搜索特定文件(更快的方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26902156/

相关文章:

java - 从 Android 中使用 Google Mirror API 附加图像不起作用

php - 使用 "LIKE"匹配mysql查询中的多个单词

django - 多语言 django 网站上的搜索功能

mysql - 在 MySQL 问题中搜索多个值

java - tomcat服务器部署时出现404错误

java - 带有部分标题的 Android GridView

java - 为什么mybatis3不支持Set foreach?

java - Eclipse QuickFix 功能

javascript - 如何将搜索框链接到我页面上的网站?

search - 如何在 solr 的多值字段中添加不同的值