File.lastModified()痛苦地慢!

时间:2010-11-29 15:55:13

标签: java file-io copy last-modified xcopy

我正在执行文件的递归副本,例如xcopy /D我只想复制较新的文件目标文件(我不能直接使用xcopy,因为我需要更改复制过程中的一些文件。)

在java中,我使用lastModified()来检查目标文件是否比源文件旧,而且速度很慢。

  • 我可以加快进程(可能使用JNI ??)?
  • 是否有其他可以更好地完成工作的复制脚本(复制新文件+正则表达式更改一些文本文件)?

无论如何都不能复制文件,因为这比检查上次修改日期(通过网络复制)需要更多时间。

4 个答案:

答案 0 :(得分:3)

你需要确定它为什么这么慢。

当您运行progrma时,您的进程的CPU利用率是多少。如果它超过50%的用户,那么你应该能够选择你的程序,如果它低于20%你没有那么多你可以做。

通常这种方法很慢,因为您正在检查的文件位于磁盘而不是内存中。如果是这种情况,您需要加快访问磁盘的速度,或者获得更快的驱动器。例如这样做SSD可以快10-100倍。

批量查询可能有所帮助。您可以使用多个线程来检查lastModified日期。例如具有固定大小的线程池并为每个文件添加任务。线程池的大小决定了一次轮询的文件数。

这允许操作系统重新排序请求以适应磁盘上的布局。注意:这在理论上很好,但你必须测试这是否会使你的操作系统/硬件上的速度更快,因为它可能会使速度变慢。 ;)

答案 1 :(得分:1)

不幸的是,Java处理查找lastModified的方式很慢(基本上它在您请求信息时查询每个文件的基础文件系统,在listFiles或类似文件上没有批量加载此数据)。

您可以调用更高效的本机程序来批量执行此操作,但任何此类解决方案都将与您部署的平台紧密相关。

答案 2 :(得分:1)

我想你是通过网络这样做的,否则副本中就没什么意义了。网络目录操作很慢,运气不好。您总是可以将文件复制到特定大小阈值以下,无论是什么使得总操作花费的时间最少。

我在这里不同意克里斯:在Java的方式上没有什么效率低得惊人,无论如何它真的必须这样做,因为你想要最新的价值。

答案 3 :(得分:1)

所以我在网络驱动器上遇到了这个问题。痛苦。我有一个包含17000多个文件的目录。在本地驱动器上,检查上次修改日期的时间不到2秒。在网络驱动器上花了58秒!当然我的应用程序是一个交互式应用程序,所以我有一些投诉。

经过一番研究后,我决定可以实现一些JNI代码来执行Windows Kernel32 findfirstfile / findnextfile / findclose来显着改进过程,但后来我有32位和64位版本等等。然后失去跨平台功能。

虽然这里有点讨厌的黑客是我做的。我的应用程序主要在Windows上运行,但我不想限制它这样做,所以我做了以下。检查我是否在Windows上运行。如果是,那么看看我是否使用本地硬盘。如果没有,那么我们将采用hackish方法。

我存储了所有不区分大小写的内容。对于可能有两个文件'ABC'和'abc'的目录的其他操作系统可能不是一个好主意。如果你需要关心这个,那么你可以通过创建一个新文件(“ABC”)和新文件(“abc”),然后使用equals方法来比较它们。对于像Windows这样的不区分大小写的文件系统,它将返回true,但在unix系统上它将返回false。

尽管在网络驱动器上花费的时间从58秒变为1.6秒可能有点过时,但我可以忍受黑客攻击。

        boolean useJaveDefaultMethod = true;

    if(System.getProperty("os.name").startsWith("Windows"))
    {
        File f2 = f.getParentFile();
        while(true)
        {
            if(f2.getParentFile() == null)
            {
                String s = FileSystemView.getFileSystemView().getSystemTypeDescription(f2);
                if(FileSystemView.getFileSystemView().isDrive(f2) && "Local Disk".equalsIgnoreCase(s))
                {
                    useJaveDefaultMethod = true;
                }
                else
                {
                    useJaveDefaultMethod = false;
                }
                break;
            }
            f2 = f2.getParentFile();
        }
    }
    if(!useJaveDefaultMethod)
    {
        try
        {
            ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "dir " + f.getParent());
            pb.redirectErrorStream(true);
            Process process = pb.start();
            InputStreamReader isr = new InputStreamReader(process.getInputStream());
            BufferedReader br = new BufferedReader(isr);

            String line;
            DateFormat df = new SimpleDateFormat("dd-MMM-yy hh:mm a");
            while((line = br.readLine()) != null)
            {
                try
                {
                    Date filedate = df.parse(line);
                    String filename = line.substring(38);
                    dirCache.put(filename.toLowerCase(), filedate.getTime());
                }
                catch(Exception ex)
                {

                }
            }
            process.waitFor();

            Long filetime = dirCache.get(f.getName().toLowerCase());
            if(filetime != null)
                return filetime;

        }
        catch(Exception Exception)
        {
        }
    }

    // this is SO SLOW on a networked drive!
    long lastModifiedDate = f.lastModified();
    dirCache.put(f.getName().toLowerCase(), lastModifiedDate);

    return lastModifiedDate;