Существует ли обходное решение для низкой производительности Java при обходе огромных каталогов?

Проблема возникает, когда у вашего сервера есть подписанный сертификат. Чтобы обойти это, вы можете добавить этот сертификат в список доверенных сертификатов вашей JVM.

В этой статье автор описывает, как получить сертификат из вашего браузера и добавить его в файл cacerts вашей JVM. Вы можете отредактировать файл JAVA_HOME/jre/lib/security/cacerts или запустить приложение с параметром -Djavax.net.ssl.trustStore. Проверьте, какой JDK / JRE вы используете, так как это часто является источником путаницы.

См. Также: Как разрешены имена серверов сертификатов SSL / Можно ли добавлять альтернативные имена с помощью keytool? Если вы столкнулись с java.security.cert.CertificateException: No name matching localhost found исключением.

17
задан Eddie 1 March 2009 в 01:56
поделиться

8 ответов

Хотя это не симпатично, я решил этот вид проблемы однажды путем передачи по каналу вывода dir/ls в файл прежде, чем запустить мое приложение и передать в имени файла.

, Если бы необходимо было сделать это в рамках приложения, Вы могли бы просто использовать system.exec (), но это создало бы некоторую злобность.

Вы спросили. Первая форма будет ослепительно быстрой, второе должно быть довольно быстрым также.

убедиться сделать один объект на строку (пустой, никакое художественное оформление, никакая графика), полный путь и рекурсивно вызвать опции Вашей выбранной команды.

РЕДАКТИРОВАНИЕ:

30 минут только для получения списка каталогов, ничего себе.

Это просто ударило меня, что при использовании должностного лица () можно добраться, это - stdout, перенаправленный в канал вместо того, чтобы писать это в файл.

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

взаимодействие может на самом деле замедлить вещи, но возможно не - Вы могли бы дать ему попытку.

, Ничего себе, я просто пошел для нахождения синтаксиса команды .exec для Вас и столкнулся с этим, возможно точно, что Вы хотите (это перечисляет каталог с помощью должностного лица и "ls" и передает результат по каналу в программу для обработки): хорошая ссылка в wayback (JГ¶rg, обеспеченный в комментарии для замены этот от солнца, которое повредила Oracle)

Так или иначе, идея проста, но разбирается, код является раздражающим. Я пойду, крадут некоторые коды из Интернета и изрубили их - brb


/**
 * Note: Only use this as a last resort!  It's specific to windows and even
 * at that it's not a good solution, but it should be fast.
 * 
 * to use it, extend FileProcessor and call processFiles("...") with a list
 * of options if you want them like /s... I highly recommend /b
 * 
 * override processFile and it will be called once for each line of output.
 */
import java.io.*;

public abstract class FileProcessor
{
   public void processFiles(String dirOptions)
   {
      Process theProcess = null;
      BufferedReader inStream = null;

      // call the Hello class
      try
      {
          theProcess = Runtime.getRuntime().exec("cmd /c dir " + dirOptions);
      }
      catch(IOException e)
      {
         System.err.println("Error on exec() method");
         e.printStackTrace();  
      }

      // read from the called program's standard output stream
      try
      {
         inStream = new BufferedReader(
                                new InputStreamReader( theProcess.getInputStream() ));  
         processFile(inStream.readLine());
      }
      catch(IOException e)
      {
         System.err.println("Error on inStream.readLine()");
         e.printStackTrace();  
      }

   } // end method
   /** Override this method--it will be called once for each file */
   public abstract void processFile(String filename);


} // end class

И спасибо кодируют донора в IBM

7
ответ дан 30 November 2019 в 13:28
поделиться

Я сомневаюсь, что проблема, касаются отчета об ошибках, на который Вы сослались. Проблемой там является "только" использование памяти, но не обязательно скорость. Если у Вас есть достаточно памяти, ошибка не важна для Вашей проблемы.

необходимо иметь размеры, является ли проблемой связанная память или нет. Включите свой журнал Сборщика "мусора" и используйте, например gcviewer для анализа использования памяти.

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

3
ответ дан 30 November 2019 в 13:28
поделиться

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

Для Linux

можно посмотреть на что-то как readdir. Можно обойти структуру каталогов как связанный список и возвратить результаты в пакетах или индивидуально.

Для окон Windows

In поведение было бы довольно подобным использованием FindFirstFile и пчела FindNextFile .

2
ответ дан 30 November 2019 в 13:28
поделиться

Альтернативе нужно было служить файлам по другому протоколу. Поскольку я понимаю, что Вы используете SMB для этого, и Java просто пытается перечислить их как регулярный файл.

проблемой здесь не мог бы быть один только Java (как делает это ведет себя при открытии того каталога с Microsoft Explorer x:\shared), По моему опыту, это также берет значительно количество времени.

можно изменить протокол на что-то как HTTP, только для выборки имен файлов. Таким образом, можно получить список файлов по http (10k строки should't быть слишком много) и позволить серверу иметь дело со списком файлов. Это было бы очень быстро, так как это будет работать с локальными ресурсами (те, которые в сервере)

Затем, когда у Вас есть список, можно обработать их один точно способом, которым Вы делаете прямо сейчас.

keypoint должен иметь механизм помощи в другой стороне узла.

это выполнимое?

Сегодня:

File [] content = new File("X:\\remote\\dir").listFiles();

for ( File f : content ) {
    process( f );
}

Предложенный:

String [] content = fetchViaHttpTheListNameOf("x:\\remote\\dir");

for ( String fileName : content ) {
    process( new File( fileName ) );
}

http сервер мог быть очень маленьким маленьким и простым файлом.

, Если это - путь, у Вас есть он прямо сейчас, что Вы делаете, должен выбрать всю 10k информацию о файлах к Вашей клиентской машине (я не знаю, сколько из той информации), когда Вам только нужно имя файла для дальнейшей обработки.

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

Дают ему попытку.

4
ответ дан 30 November 2019 в 13:28
поделиться

Если необходимо в конечном счете обработать все файлы, то наличие, Повторяемое по Строке [], не даст Вам преимущества, когда необходимо будет все еще пойти и выбрать целый список файлов.

1
ответ дан 30 November 2019 в 13:28
поделиться

Интересно, почему существуют 10k файлы в каталоге. Некоторые файловые системы не работают хорошо с таким количеством файлов. Существуют ограничения специфических особенностей для файловых систем как макс. сумма файлов на каталог и макс. количество уровней подкаталога.

я решаю подобную проблему с решением для итератора.

я должен был идти через огромные каталоги и несколько уровней дерева каталогов рекурсивно.

я пробую FileUtils.iterateFiles () свободного городского населения Apache io. Но это реализует итератор путем добавления всех файлов в Списке и затем возврата List.iterator (). Это очень плохо для памяти.

, Таким образом, я предпочитаю писать что-то вроде этого:

private static class SequentialIterator implements Iterator<File> {
    private DirectoryStack dir = null;
    private File current = null;
    private long limit;
    private FileFilter filter = null;

    public SequentialIterator(String path, long limit, FileFilter ff) {
        current = new File(path);
        this.limit = limit;
        filter = ff;
        dir = DirectoryStack.getNewStack(current);
    }

    public boolean hasNext() {
        while(walkOver());
        return isMore && (limit > count || limit < 0) && dir.getCurrent() != null;
    }

    private long count = 0;

    public File next() {
        File aux = dir.getCurrent();
        dir.advancePostition();
        count++;
        return aux;
    }

    private boolean walkOver() {
        if (dir.isOutOfDirListRange()) {
            if (dir.isCantGoParent()) {
                isMore = false;
                return false;
            } else {
                dir.goToParent();
                dir.advancePostition();
                return true;
            }
        } else {
            if (dir.isCurrentDirectory()) {
                if (dir.isDirectoryEmpty()) {
                    dir.advancePostition();
                } else {
                    dir.goIntoDir();
                }
                return true;
            } else {
                if (filter.accept(dir.getCurrent())) {
                    return false;
                } else {
                    dir.advancePostition();
                    return true;
                }
            }
        }
    }

    private boolean isMore = true;

    public void remove() {
        throw new UnsupportedOperationException();
    }

}

Примечание, что итератор заходит в сумму файлов iterateds и он имеет FileFilter также.

И DirectoryStack:

public class DirectoryStack {
    private class Element{
        private File files[] = null;
        private int currentPointer;
        public Element(File current) {
            currentPointer = 0;
            if (current.exists()) {
                if(current.isDirectory()){
                    files = current.listFiles();
                    Set<File> set = new TreeSet<File>();
                    for (int i = 0; i < files.length; i++) {
                        File file = files[i];
                        set.add(file);
                    }
                    set.toArray(files);
                }else{
                    throw new IllegalArgumentException("File current must be directory");
                }
            } else {
                throw new IllegalArgumentException("File current not exist");
            }

        }
        public String toString(){
            return "current="+getCurrent().toString();
        }
        public int getCurrentPointer() {
            return currentPointer;
        }
        public void setCurrentPointer(int currentPointer) {
            this.currentPointer = currentPointer;
        }
        public File[] getFiles() {
            return files;
        }
        public File getCurrent(){
            File ret = null;
            try{
                ret = getFiles()[getCurrentPointer()];
            }catch (Exception e){
            }
            return ret;
        }
        public boolean isDirectoryEmpty(){
            return !(getFiles().length>0);
        }
        public Element advancePointer(){
            setCurrentPointer(getCurrentPointer()+1);
            return this;
        }
    }
    private DirectoryStack(File first){
        getStack().push(new Element(first));
    }
    public static DirectoryStack getNewStack(File first){
        return new DirectoryStack(first);
    }
    public String toString(){
        String ret = "stack:\n";
        int i = 0;
        for (Element elem : stack) {
            ret += "nivel " + i++ + elem.toString()+"\n";
        }
        return ret;
    }
    private Stack<Element> stack=null;
    private Stack<Element> getStack(){
        if(stack==null){
            stack = new Stack<Element>();
        }
        return stack;
    }
    public File getCurrent(){
        return getStack().peek().getCurrent();
    }
    public boolean isDirectoryEmpty(){
        return getStack().peek().isDirectoryEmpty();
    }
    public DirectoryStack downLevel(){
        getStack().pop();
        return this;
    }
    public DirectoryStack goToParent(){
        return downLevel();
    }
    public DirectoryStack goIntoDir(){
        return upLevel();
    }
    public DirectoryStack upLevel(){
        if(isCurrentNotNull())
            getStack().push(new Element(getCurrent()));
        return this;
    }
    public DirectoryStack advancePostition(){
        getStack().peek().advancePointer();
        return this;
    }
    public File[] peekDirectory(){
        return getStack().peek().getFiles();
    }
    public boolean isLastFileOfDirectory(){
        return getStack().peek().getFiles().length <= getStack().peek().getCurrentPointer();
    }
    public boolean gotMoreLevels() {
        return getStack().size()>0;
    }
    public boolean gotMoreInCurrentLevel() {
        return getStack().peek().getFiles().length > getStack().peek().getCurrentPointer()+1;
    }
    public boolean isRoot() {
        return !(getStack().size()>1);
    }
    public boolean isCurrentNotNull() {
        if(!getStack().isEmpty()){
            int currentPointer = getStack().peek().getCurrentPointer();
            int maxFiles = getStack().peek().getFiles().length;
            return currentPointer < maxFiles;
        }else{
            return false;
        }
    }
    public boolean isCurrentDirectory() {
        return getStack().peek().getCurrent().isDirectory();
    }
    public boolean isLastFromDirList() {
        return getStack().peek().getCurrentPointer() == (getStack().peek().getFiles().length-1);
    }
    public boolean isCantGoParent() {
        return !(getStack().size()>1);
    }
    public boolean isOutOfDirListRange() {
        return getStack().peek().getFiles().length <= getStack().peek().getCurrentPointer();
    }

}
0
ответ дан 30 November 2019 в 13:28
поделиться

Используя Повторяемое не подразумевает, что Файлы будут переданы потоком Вам. На самом деле обычно противоположное. Таким образом, массив обычно быстрее, чем Повторяемое.

0
ответ дан 30 November 2019 в 13:28
поделиться

Вы уверены, что это происходит из-за Java, не только общей проблемы с наличием 10k записи в одном каталоге, особенно по сети?

Вы попытались писать программу подтверждения концепции, чтобы сделать то же самое в C использование функций win32 findfirst/findnext, чтобы видеть, является ли это немного быстрее?

я не знаю входы и выходы SMB, но я сильно подозреваю, что ему нужно распространение в прямом и обратном направлениях для каждого файла в списке - который не будет быстрым, особенно по сети с умеренной задержкой.

Наличие 10k строки в массиве походит на что-то, что не должно облагать налогом современный Java VM слишком много также.

0
ответ дан 30 November 2019 в 13:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: