如何加快Windows上的Java递归文件搜索?

时间:2014-09-11 22:13:55

标签: java linux windows optimization

我正在使用Java 8搜索文件目录并提取音乐文件。当我在Linux(Debian Wheezy)上运行我的代码时,它在大约20秒内完成。但是,当我在Windows 8.1(相同的机器!)中运行相同的代码时,它需要非常长的时间,所以它确实无法使用。我已经确定过程正在发生,应该非常缓慢。在Linux变体找到所有2500个文件的时候,Windows变体已找到大约100个。

以下是代码:

public int List(String path) throws InterruptedException, IOException {
    //Linux Variant
    if (HomeScreen.os.equals("Linux")) {
        File root = new File(path);
        File[] list = root.listFiles();
        Arrays.sort(list);
        if (list == null) {
            return 0;
        }

        for (File f : list) {
            if (f.isDirectory()) {
                List(f.getAbsolutePath());

            } else if (f.isFile()) {
                String outPath = f.getAbsolutePath();
                try {
                    String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
                    if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3")) {
                        String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 6);
                        lm.addElement(fulltrack);
                        numbers++;
                    }
                } catch (Exception e) {
                    System.out.println(outPath + " is not a valid file!!!!!");
                }
                HomeScreen.Library.setModel(lm);

            }

        }
    //Windows variant
    } else if (HomeScreen.os.equals("Windows 8.1")){
        System.out.println("Using " + HomeScreen.os + " methods...");
        File root = new File(path);
        File[] list = root.listFiles();
        Arrays.sort(list);
        if (list == null) {
            return 0;
        }

        for (File f : list) {
            if (f.isDirectory()) {
                List(f.getAbsolutePath());

            } else if (f.isFile()) {
                String outPath = f.getAbsolutePath();
                try {
                    String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
                    if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3")) {
                        String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 9);
                        lm.addElement(fulltrack);
                        numbers++;
                    }
                } catch (Exception e) {
                    System.out.println(outPath + " is not a valid file!!!!!");
                }
                HomeScreen.Library.setModel(lm);

            }

        }
    }
    return numbers;
}

我还是Java新手,所以我不确定如何优化Windows代码。有没有什么方法可以加速,或者Windows用户注定要喝咖啡等待加载?

顺便提一下,我在使用Windows时将此方法放在一个线程中,以便在等待时可以完成其他任务,但这绝对不是一个理想的解决方案。正在搜索的驱动器是7200转硬盘,并且安装了8GB RAM。

2 个答案:

答案 0 :(得分:0)

尝试新的Java 8流API,它允许您执行所有操作(排序过滤器forEach) 在一个循环中! 并行:

这是你改变的代码(你可能需要修复一些我喜欢的HomeScreen部分)

        Arrays.asList(root.listFiles())
                                   .parallelStream()
                                   .filter(file -> file != null)
                                   .forEach(file -> {
                                       if (file.isDirectory())
                                       {
                                           List(file.getAbsolutePath());
                                       }
                                       else if (file.isFile())
                                       {
                                           String outPath = file.getAbsolutePath();
                                           try
                                           {
                                               String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
                                               if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3"))
                                               {
                                                   String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 9);
                                                   lm.addElement(fulltrack);
                                                   numbers++;
                                               }
                                           } catch (Exception e)
                                           {
                                               System.out.println(outPath + " is not a valid file!!!!!");
                                           }
                                           HomeScreen.Library.setModel(lm);
                                       }
                                   });

答案 1 :(得分:0)

根据Lorenzo Boccaccia关联的question评论中的建议,我选择newDirectoryStream。它逐个返回文件,这应该更快。

我也考虑使用多线程。使用单个线程,您几乎一直在等待磁盘。现代磁盘能够处理多个未完成的请求,因此使用2-4个线程应该有所帮助。


旁注:没有理由为Linux和Windows编写不同的代码。可能需要进行微小的更改,但应该通过一些小帮手方法来处理。

绝不写下像

这样的内容
if (HomeScreen.os.equals("Linux")) {
    ...
} else if (HomeScreen.os.equals("Windows 8.1")) {
    ...
}

如果它是" Windows 8.2"?