Вопрос

Я делаю рекурсивную копию файлов и как xcopy /D Я хочу только скопировать новые файлы назначения файлов (я не можешь использовать xcopy Непосредственно с тех пор, как мне нужно изменить файлы в процессе копирования).

В Java я использую lastModified() Чтобы проверить, является ли файл назначения старше исходного файла, и он очень медленно.

  • Могу ли я ускорить процесс (может быть, используя JNI ??)?
  • Есть ли какие-либо другие сценарии копирования, которые могут сделать работу лучше (копировать новые файлы + Regexp изменить некоторые текстовые файлы)?

Копирование файлов в любом случае не является опцией, так как это займет больше времени, чем проверка последней модифицированной даты (копирование по сети).

Это было полезно?

Решение

Вы должны определить, почему это так медленно.

Когда вы запускаете Programma, каково использование процессора вашего процесса. Если это более 50% пользователей, то вы сможете найти свою программу, если ее меньше 20%, что вы не можете сделать.

Обычно этот метод медленно, потому что файл, который вы изучаете на диске, а не в памяти. Если это так, вам нужно ускорить, как вы получаете доступ к вашему диску, или получите более быстрый диск. Например, SSD может быть 10-100x быстрее при этом.

Большой объем может помочь. Вы можете сделать это, используя несколько потоков для проверки последней даты. Например, у бассейна резьбы фиксированного размера и добавьте задачу для каждого файла. Размер пула резьбы определяет количество файлов, опрошенных одновременно.

Это позволяет ОС повторно заказать запросы на предмет макета на диске. ПРИМЕЧАНИЕ. Это нормально в теории, но вы должны проверить, делает это быстрее в вашей ОС / оборудотере, так как его так же, как только для того, чтобы сделать вещи медленными. ;)

Другие советы

К сожалению, то, как обрабатывает Java, глядя в LastModified, медленный (в основном это запрашивает базовую файловую систему для каждого файла, поскольку вы запрашиваете информацию, нет навалочной загрузки этих данных на ListFiles или аналогично).

Вы могли бы потенциально вызвать более эффективную нативную программу, чтобы сделать это навалом, но любое такое решение будет тесно связано с платформой, которую вы развертываете.

Я представляю, что вы делаете это по сети, в противном случае в копии будет небольшая точка. Сетевые операции каталогов медленные, неудача. Вы всегда можете просто скопировать файл ниже определенного порога размера, что бы ни заработало полную эксплуатацию.

Я не согласен с KRIS здесь: нет ничего поразительного неэффективного в том, как Java делает это, и в любом случае это действительно должно делать это, потому что вы хотите, чтобы получить последнее значение.

Поэтому я бежал через это на сетевых дисках. Болезненный. У меня был каталог с 17000+ файлами на нем. На местном диске потребовалось менее 2 секунд, чтобы проверить последнюю модифицированную дату. На сетевом диске потребовалось 58 секунд !!! Конечно, мое приложение - это интерактивное приложение, поэтому у меня были некоторые жалобы.

После некоторых исследований я решил, что можно будет осуществить какой-то код JNI для выполнения Windows Kernel32 FindFirstFile / FindnextFile / FindClose, чтобы значительно улучшить процесс, но тогда у меня была 32 и 64-битная версия и т. Д. тьфу. а затем потерять перекрестные возможности платформы.

Хотя немного неприятного взлома вот что я сделал. Мое приложение работает в Windows в основном, но я не хотел ограничить его сделать это, чтобы я сделал следующее. Проверьте, работаю ли я в Windows. Если так, то посмотрите, использую ли я местный жесткий диск. Если нет, то мы собираемся сделать хакерский метод.

Я сохранил все нечувствительные к регистру. Вероятно, не отличная идея для других ОС, которые могут иметь каталог с обоими файлами «ABC» и «ABC». Если вам нужно позаботиться об этом, вы можете решить, создав новый файл («ABC») и новый файл («ABC»), а затем используя метод равенства для сравнения их. В случае нечувствительных к регистру файловых систем, таких как Windows, она вернет True, но на системах Unix она вернет ложь.

Хотя это может быть немного взлом времени, когда он взял, пошел от 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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top