Java скопировать папку, исключая некоторые внутренние файлы - PullRequest
5 голосов
/ 25 августа 2011

У меня есть папка с такой структурой

* 1003 Главная папка *

   --Sub1  
         --File .scl
         --File .awl
         --Other files
   --Sub2  
         --Files
   --Sub3
   --Sub4

Я хочу скопировать его в другое место, но я хочу, чтобы избежать Sub3 и (в зависимости от ситуации) некоторый файл из Sub1

Вот выдержка из того, что я сделал до сих пор:

FileUtils.copyDirectory(srcDir, dstDir, new FileFilter() {
        public boolean accept(File pathname) {
            // We don't want 'Sub3' folder to be imported
            // + look at the settings to decide if some format needs to be
            // excluded
            String[] ignoreList= new String[]{
                    !Settings.getSiemensOptionAWL() ? ".awl":"uselessStringWilNeverBeFound",
                    !Settings.getSiemensOptionSCL() ? ".scl":"uselessStringWilNeverBeFound",
                    "Sub3"
            };

            return !(ignoreFile(pathname, ignoreList) && pathname
                    .isDirectory());
        }
    }, true);


    public static boolean ignoreFile(File file, String[] ignoreList) {
        for (final String ignoreStr : ignoreList)
            if (file.getAbsolutePath().contains(ignoreStr))
                return true;
        return false;
    }

Видимо, это швы на работу. Но я думаю, что это очень уродливое решение .... Кто-нибудь знает лучший способ?

P.S: Конечно, Settings.getSiemensOptionAWL () - это просто логическая функция, которая возвращает мое решение

Ответы [ 4 ]

4 голосов
/ 25 августа 2011

Другие варианты, предложенные здесь, хороши, однако другой альтернативой является объединение нескольких более простых FileFilters (что может быть излишним, конечно!)

public class FailFastFileFilter implements FileFilter {
    protected final List<FileFilter> children = new ArrayList<FileFilter>();

    public FailFastFileFilter(FileFilter... filters) {
        for (FileFilter filter: filters) {
            if (filter != null)
                this.filters.add(filter);
        }       
    }

    public boolean accept(File pathname) {
        for (FileFilter filter: this.filters) {
            if (!filter.accept(pathname)) {
                return false; // fail on the first reject
            }
        }

        return true;
    }
}

Затем просто объедините короткие, краткие FileFilters для случая Sub3, .scl и .awl. Пример FailFastFileFilter, который я показал выше, позволит вам указать null в качестве одного из фильтров (чтобы вы могли использовать встроенные операторы if, чтобы определить, применяются ли определенные FileFilters)

Для завершения приведу общее представление о том, как реализовать дочерние фильтры для случаев Sub1 и Sub3.

Во-первых, фильтр для исключения файлов с определенным расширением в каталоге:

public class ExcludeExtensionInDirFileFilter implements FileFilter {
    protected final String parentFolder;
    protected final String extension;

    public ExtensionFileFilter(String parentFolder, String extension) {
        this.parentFolder = parentFolder;
        this.extension = extension.toLowerCase();
    }

    public boolean accept(File file) {
        if (!file.isDirectory() && file.getParentFile().getName().equalsIgnoreCase(parentFolder))
            return !file.getAbsolutePath().toLowerCase().endsWith(extension);
        else
            return true;
    }
}

Затем исключить каталог:

public class ExcludeDirFileFilter implements FileFilter {
    protected final String name;

    public ExcludeDirFileFilter(String name) {
        this.name = name.toLowerCase();
    }

    public boolean accept(File file) {
        if (file.isDirectory() && file.getName().equalsIgnoreCase(name))
            return false;
        else
            return true;
    }
}

Настройка FailFastFileFilter будет выглядеть примерно так:

FileFilter filters = new FailFastFileFilter(
    new ExcludeDirFileFilter("Sub3"), // always exclude Sub3
    (!Settings.getSiemensOptionAWL() ? new ExcludeExtensionInDirFileFilter("Sub1",".awl"), null), // Exclude Sub1/*.awl if desired
    (!Settings.getSiemensOptionSCL() ? new ExcludeExtensionInDirFileFilter("Sub1",".scl"), null) // Exclude Sub1/*.scl if desired
);

FileUtils.copyDirectory(srcDir, dstDir, filters);
3 голосов
/ 25 августа 2011

Я думаю, что уродство связано с введением ignoreFile(), которое обязательно теряет некоторую полезную информацию (какие строки действительно имеют значение, какие строки являются расширениями файлов и т. Д.) Кроме того, этот массив будет создаваться для каждого файла в ваша иерархия, которая крайне неэффективна. Рассмотрим что-то вроде этого:

FileUtils.copyDirectory(srcDir, dstDir, new FileFilter() {
    public boolean accept(File pathname) {
        // We don't want 'Sub3' folder to be imported
        // + look at the settings to decide if some format needs to be
        // excluded
        String name = pathname.getName();
        if (!Settings.getSiemensOptionAWL() && name.endsWith(".awl"))
            return false;
        if (!Settings.getSiemensOptionSCL() && name.endsWith(".scl"))
            return false;

        return !(name.equals("Sub3") && pathname.isDirectory());
    }
}, true);
1 голос
/ 25 августа 2011

Зафиксирован ли этот шнур в камне? Может быть, что-то вроде

new FileFilter() {
    public boolean accept(File pathname) {
        String path = pathname.getAbsolutePath().toLowerCase();

        return (!pathname.isDirectory() || path.endsWith("sub3")) &&
            (!Settings.getSiemensOptionAWL() && path.endsWith(".awl")) &&
            (!Settings.getSiemensOptionSCL() && path.endsWith(".scl"));
    }
}
0 голосов
/ 25 августа 2011

выглядит довольно чисто для меня.Только не помещайте все это непосредственно в вызывающий код, чтобы вам не приходилось все время на него смотреть.Создайте свой собственный класс CopySubDir, который скрывает весь этот код и предоставляет простой для понимания интерфейс.Тогда вызывающий код будет выглядеть чисто.

...