6 Stimmen

Java kopieren Sie einen Ordner und schließen Sie einige interne Dateien aus.

Ich habe einen Ordner mit dieser Struktur

mainFolder

   --Sub1  
         --Datei .scl
         --Datei .awl
         --Andere Dateien
   --Sub2  
         --Dateien
   --Sub3
   --Sub4

Ich möchte es an einen anderen Ort kopieren, aber ich möchte vermeiden, dass Sub3 und (je nach Situation) einige Dateien aus Sub1 kopiert werden

Hier ist ein Auszug aus dem bisherigen Vorgehen:

FileUtils.copyDirectory(srcDir, dstDir, new FileFilter() {
        public boolean accept(File pathname) {
            // Wir möchten den Ordner 'Sub3' nicht importieren
            // + Überprüfen der Einstellungen, um zu entscheiden, ob ein bestimmtes Format ausgeschlossen werden muss
            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;
    }

Anscheinend funktioniert es. Aber ich denke, dass es eine sehr hässliche Lösung ist.... Kennt jemand einen besseren Weg?

P.S: natürlich ist Settings.getSiemensOptionAWL() einfach eine boolesche Funktion, die meine Entscheidung zurückgibt

5voto

Peter Punkte 945

Die anderen hier vorgeschlagenen Optionen sind gut, jedoch eine weitere Alternative besteht darin, mehrere einfachere FileFilter ineinander zu verschachteln (was natürlich übertrieben sein kann!)

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

    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; // beim ersten Ablehnen fehlschlagen
            }
        }

        return true;
    }
}

Dann kombinieren Sie einfach kurze, prägnante FileFilter für den Fall Sub3, den Fall .scl und den Fall .awl. Der oben gezeigte FailFastFileFilter würde es Ihnen ermöglichen, null als einen der Filter anzugeben (damit Sie Inline-If-Anweisungen verwenden können, um festzustellen, ob bestimmte FileFilter angewendet werden)

Zum Zwecke der Vollständigkeit hier eine allgemeine Vorstellung davon, wie ich die Kindfilter für die Fälle Sub1 und Sub3 implementieren würde.

Zunächst ein Filter, um Dateien mit einer bestimmten Erweiterung in einem Verzeichnis auszuschließen:

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;
    }
}

Dann zum Ausschließen eines Verzeichnisses:

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;
    }
}

Die Einrichtung des FailFastFileFilter würde dann ungefähr so aussehen:

FileFilter filters = new FailFastFileFilter(
    new ExcludeDirFileFilter("Sub3"), // immer Sub3 ausschließen
    (!Settings.getSiemensOptionAWL() ? new ExcludeExtensionInDirFileFilter("Sub1",".awl"), null), // Sub1/*.awl ausschließen, falls gewünscht
    (!Settings.getSiemensOptionSCL() ? new ExcludeExtensionInDirFileFilter("Sub1",".scl"), null) // Sub1/*.scl ausschließen, falls gewünscht
);

FileUtils.copyDirectory(srcDir, dstDir, filters);

3voto

Ernest Friedman-Hill Punkte 79357

Ich denke, die Hässlichkeit kommt daher, dass ignoreFile() eingeführt wird, was zwangsläufig einige der nützlichen Informationen verliert (welche Zeichenfolgen tatsächlich wichtig sind, welche Zeichenfolgen Dateierweiterungen sind, usw.) Außerdem wird dieses Array für jede Datei in Ihrer Hierarchie erstellt, was äußerst ineffizient ist. Überlegen Sie stattdessen etwas wie dies:

FileUtils.copyDirectory(srcDir, dstDir, new FileFilter() {
    public boolean accept(File pathname) {
        // Wir möchten, dass der Ordner 'Sub3' nicht importiert wird
        // + schauen Sie sich die Einstellungen an, um zu entscheiden, ob ein bestimmtes Format ausgeschlossen werden muss
        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);

1voto

vickirk Punkte 3847

Ist der Fall dieser Zeichenfolge in Stein gemeißelt? Vielleicht so etwas wie

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"));
    }
}

-1voto

Sarel Botha Punkte 12053

Sieht ziemlich sauber aus für mich. Legen Sie es einfach nicht direkt in den Aufrufcode, damit Sie es nicht die ganze Zeit ansehen müssen. Erstellen Sie Ihre eigene CopySubDir-Klasse, die all diesen Code verbirgt und eine einfach zu verstehende Schnittstelle dazu bereitstellt. Dann wird der Aufrufcode sauber aussehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X