Dateien in Java einlesen und speichern.


Das vorhandene "Wirrwarr" ist weniger unnütz als gedacht ...

Als ich begonnen habe, Java zu lernen und mich die ersten Mal mit den Klassen auseinandergesetzt habe, die zum Filehandling bereitgestellt wurden, fand ich ein großes Wirrwarr vor und fragte mich, wer bitte ein solches nichtsnutziges Chaos fabriziert hatte, wo in anderen Sprachen kurze, knappe Befehle für die gleiche Aufgabe ausreichten.

Der Aha-Effekt kam erst später, als ich plötzlich feststellte, wie einfach es ist, statt aus einer Datei aus einem String oder einem Datenstrom zu lesen respektive zu schreiben.

Als ich dann "Entwurfsmuster von Kopf bis Fuß" gelesen hatte, wusste ich spätestens, warum die Javaentwickler dieses "Chaos" fabriziert hatten, wie das zugehörige Entwurfsmuster heißt und wozu all das gut ist.

... aber es ist dennoch in der Praxis unhandlich.

Gerade in der Verquickung mit den Checked Exceptions ist die Verwendung der von Java vorgesehenen Klassen zum Filehandling alles andere als eine Freude. So kommt man über kurz oder lang auf die Idee, diese ganzen weniger schönen Dinge zu kapseln, wie man auch eine fremde API kapseln würde, um sie für die eigenen Programme glatter verwenden zu können. So kann man sogar die verwendete Bibliothek austauschen, ohne Anpassungen an unzähligen Stellen in den verschiedensten Projekten vornehmen zu müssen.

Ein solches Vorgehen hat natürlich nicht nur Vorteile:

Vorteile

Nachteile

Für mich überwiegen hier klar die Vorteile. Im weiteren will ich meine Lösung vorstellen.

Meine Klassen zum Filehandling

Lesen

Schreiben

Suchen in Dateien

Weitere Klassen

Exemplarische Klassen

Writer

Writer

package de.duehl.basics.io;

import java.util.List;

import de.duehl.basics.io.exceptions.IORuntimeException;

public interface Writer {

    /**
     * Schreibt den übergebenen String auf den Writer.
     *
     * @param text
     *            Der auszugebende Text.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    void write(String text);

    /**
     * Schreibt die übergebene Zahl auf den Writer.
     *
     * @param number
     *            Die auszugebende Zahl.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    void write(int number);

    /** Gibt einen Zeilenumbruch aus. */
    void writeln();

    /**
     * Schreibt den übergebenen String auf den Writer und fügt einen
     * Zeilenumbruch an.
     *
     * @param text
     *            Der auszugebende Text.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    void writeln(String text);

    /**
     * Schließt den Writer.
     *
     * @throws IORuntimeException
     *             Falls beim Schließen ein Fehler auftrat.
     */
    void close();

    /**
     * Veranlasst den Writer alle Daten im Zwischenspeicher in die Datei zu
     * schreiben.
     *
     * @throws IORuntimeException
     *             Falls beim flush ein Fehler auftrat.
     */
    void flush();

    /**
     * Schreibt alle Zeilen der übergebenen Liste auf den Writer und fügt
     * jeweils einen Zeilenumbruch an.
     *
     * @param list
     *            Die Liste mit den auszugebenden Zeilen.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    void writeAllLines(List list);

    /**
     * Schreibt eine Menge von Strings tabgetrennt in eine Zeile und fügt einen
     * Zeilenumbruch an.
     *
     * @param fields
     *            Menge der tabgetrennt auszugebenden Strings.
     */
    void writeFieldsLine(List fields);

    /**
     * Schreibt eine Menge von Strings tabgetrennt in eine Zeile und fügt einen
     * Zeilenumbruch an.
     *
     * @param fields
     *            Menge der tabgetrennt auszugebenden Strings.
     */
    void writeFieldsLine(String ... strings);

}

FineFileWriter

FineFileWriter

package de.duehl.basics.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;

import de.duehl.basics.io.exceptions.IORuntimeException;
import de.duehl.basics.text.Text;

/**
 * Diese Klasse stellt einen Writer dar, im Falle von Fehlern werden Ausnahmen geworfen.
 *
 * @version 1.03     2016-10-14
 * @author Christian Dühl
 */

public class FineFileWriter implements Writer {

    /** Der Schreiberling. */
    private final OutputStreamWriter writer;

    /** Name der Ausgabedatei. */
    private final String fileName;

    /** Gibt an ob an eine bestehende Datei angehängt wird. */
    private final boolean append;

    /** Zeichensatz der einzulesenden Datei (z.B. "ISO-8859-1", "UTF-8"). */
    private final Charset charset;

    /**
     * Konstruktor aus einem File.
     *
     * @param file
     *            Zu schreibende Datei.
     * @throws UnsupportedEncodingException
     * @throws FileNotFoundException
     */
    public FineFileWriter(File file) {
        this(file.getAbsolutePath(), false);
    }

    /**
     * Konstruktor aus einem Dateinamen.
     *
     * @param fileName
     *            Der Name der auszugebenden Datei.
     * @throws UnsupportedEncodingException
     * @throws FileNotFoundException
     */
    public FineFileWriter(String fileName) {
        this(fileName, false);
    }

    /**
     * Konstruktor zum Anlegen oder Anhängen an eine Datei im Format "ISO-8859-1".
     *
     * @param fileName
     *            Der Name der auszugebenden Datei.
     * @param append
     *            Gibt an, ob an die Datei angehängt wird.
     * @throws IORuntimeException
     *             Wenn die Datei (der Pfad) nicht gefunden wurde oder falls eine unbekannte
     *             Kodierung an den OutputStreamWriter übergeben wurde.
     */
    public FineFileWriter(String fileName, boolean append) {
        this(fileName, Charset.ISO_8859_1, append);
    }

    /**
     * Konstruktor zum Anlegen einer neuen Datei mit Angabe des Zeichensatz.
     *
     * @param fileName
     *            Der Name der auszugebenden Datei.
     * @param charset
     *            Zeichensatz der zu schreibenden Datei.
     * @throws IORuntimeException
     *             Wenn die Datei (der Pfad) nicht gefunden wurde oder falls eine unbekannte
     *             Kodierung an den OutputStreamWriter übergeben wurde.
     */
    public FineFileWriter(String fileName, Charset charset) {
        this(fileName, charset, false);
    }

    /**
     * Konstruktor
     *
     * @param file
     *            Der Name der auszugebenden Datei.
     * @param charset
     *            Zeichensatz der zu schreibenden Datei.
     * @param append
     *            Gibt an, ob an die Datei angehängt wird.
     * @throws IORuntimeException
     *             Wenn die Datei (der Pfad) nicht gefunden wurde oder falls eine unbekannte
     *             Kodierung an den OutputStreamWriter übergeben wurde.
     */
    public FineFileWriter(String file, Charset charset, boolean append) {
        this.fileName = file;
        this.append = append;
        this.charset = charset;
        this.writer = openWriter();
    }

    /**
     * Öffnet den Writer. Die Fehlerbehandlung erfolgt hier.
     *
     * @return Writer-Objekt.
     *
     * @throws IORuntimeException
     *             Wenn die Datei (der Pfad) nicht gefunden wurde oder falls eine unbekannte
     *             Kodierung an den OutputStreamWriter übergeben wurde.
     */
    private OutputStreamWriter openWriter() {
        try {
            return tryToOpenWriter();
        }
        catch (FileNotFoundException e) {
            throw new IORuntimeException("Der Pfad zur Ausgabedatei '" + fileName + "' wurde "
                    + "nicht gefunden. (" + e.getMessage() + ")");
        }
        catch (UnsupportedEncodingException e) {
            throw new IORuntimeException("Bei der Erzeugung des OutputStreamWriters für die "
                    + "Eingabedatei '" + fileName + "' wurde eine nicht unterstützte Kodierung "
                    + "verwendet. (" + e.getMessage() + ")");
        }
    }

    /**
     * Öffnet den Writer.
     *
     * @return Writer-Objekt.
     *
     * @throws FileNotFoundException
     *             Wenn die Datei (der Pfad) nicht gefunden wurde.
     * @throws UnsupportedEncodingException
     *             Falls eine unbekannte Kodierung an den OutputStreamWriter
     *             übergeben wurde.
     */
    private OutputStreamWriter tryToOpenWriter() throws FileNotFoundException,
            UnsupportedEncodingException {
        OutputStream outputStream = new FileOutputStream(fileName, append);
        return new OutputStreamWriter(outputStream, charset.getCharsetAsString());
    }

    /**
     * Schreibt den übergebenen String auf den Writer.
     *
     * @param text
     *            Der auszugebende Text.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    @Override
    public void write(String text) {
        try {
            writer.write(text);
            //writer.flush(); /* bremst */
        }
        catch (IOException e) {
            throw new IORuntimeException("Beim Schreiben in die Datei '" + fileName + "' trat ein "
                    + "Fehler auf. (" + e.getMessage() + ")");
        }
    }

    /**
     * Schreibt die übergebene Zahl auf den Writer.
     *
     * @param number
     *            Die auszugebende Zahl.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    @Override
    public void write(int number) {
        write(Integer.toString(number));
    }

    /** Gibt einen Zeilenumbruch aus. */
    @Override
    public void writeln() {
        write(Text.LINE_BREAK);
    }

    /**
     * Schreibt den übergebenen String auf den Writer und fügt einen Zeilenumbruch an.
     *
     * @param text
     *            Der auszugebende Text.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    @Override
    public void writeln(String text) {
        write(text + Text.LINE_BREAK);
    }

    /**
     * Schließt den Writer.
     *
     * @throws IORuntimeException
     *             Falls beim Schließen ein Fehler auftrat.
     */
    @Override
    public void close() {
        try {
            writer.close();
        }
        catch (IOException e) {
            throw new IORuntimeException("Beim Schließen der Datei '" + fileName + "' trat ein "
                    + "Fehler auf. (" + e.getMessage() + ")");
        }
    }

    /**
     * Veranlasst den Writer alle Daten im Zwischenspeicher in die Datei zu schreiben.
     *
     * @throws IORuntimeException
     *             Falls beim flush ein Fehler auftrat.
     */
    @Override
    public void flush() {
        try {
            writer.flush();
        }
        catch (IOException e) {
            throw new IORuntimeException("Beim Flushen der Datei '" + fileName + "' trat ein "
                    + "Fehler auf. (" + e.getMessage() + ")");
        }
    }

    /**
     * Schreibt alle Zeilen der übergebenen Liste auf den Writer und fügt jeweils einen
     * Zeilenumbruch an.
     *
     * @param list
     *            Die Liste mit den auszugebenden Zeilen.
     * @throws IORuntimeException
     *             Falls beim Schreiben ein Fehler auftrat.
     */
    @Override
    public void writeAllLines(List list) {
        for (String text : list) {
            write(text + Text.LINE_BREAK);
        }
    }

    /**
     * Schreibt eine Menge von Strings tabgetrennt in eine Zeile und fügt einen Zeilenumbruch an.
     *
     * @param fields
     *            Menge der tabgetrennt auszugebenden Strings.
     */
    @Override
    public void writeFieldsLine(List fields) {
        boolean firstField = true;
        for (String field : fields) {
            if (firstField) {
                firstField = false;
            }
            else {
                write("\t");
            }
            write(field);
        }
        writeln();
    }

    /**
     * Schreibt eine Menge von Strings tabgetrennt in eine Zeile und fügt einen Zeilenumbruch an.
     *
     * @param fields
     *            Menge der tabgetrennt auszugebenden Strings.
     */
    @Override
    public void writeFieldsLine(String ... fields) {
        writeFieldsLine(Arrays.asList(fields));
    }

}

Reader

Reader

package de.duehl.basics.io;

import java.util.List;

import de.duehl.basics.io.exceptions.IORuntimeException;

public interface Reader {

    /**
     * Liest die nächste Zeile aus der Datei ein.
     *
     * @return Die nächste Zeile oder null, falls das Ende der Datei erreicht
     *         wurde.
     * @throws IORuntimeException
     *             Falls die Zeile nicht eingelesen werden konnte.
     */
    String readNextLine();

    /** Liefert die aktuelle Zeilennummer zurück. */
    int getLineNumber();

    /**
     * Schließt den Reader.
     *
     * @throws IORuntimeException
     *             Wenn es beim Schließen zu Problemen kam.
     */
    void close();

    /**
     * Gibt den Dateiinhalt (falls schon gelesen wurde: ab der momentanen
     * Stelle) als Liste von Strings zurück.
     *
     * @return Liste mit dem Dateiinhalt als Strings.
     */
    List readFileToListOfStrings();

    /**
     * Gibt den Dateiinhalt (falls schon gelesen wurde: ab der momentanen
     * Stelle) als einen String zurück.
     *
     * @return String mit dem Dateiinhalt.
     */
    String readFileToString();

    /** Liest eine tabgetrennte Zeile ein. */
    List readFieldsLine();

}

FineFileReader

FineFileReader

package de.duehl.basics.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import de.duehl.basics.io.exceptions.IORuntimeException;

/**
 * Diese Klasse öffnet, liest aus und schließt Dateien. Ehemals 'OpenDataFile', dann 'FileReader'.
 *
 * @version 1.05     2016-10-14
 * @author Christian Dühl
 */

public class FineFileReader implements Reader {

    /** Die Datei, die geöffnet und gelesen werden soll. */
    private final String fileName;

    /** Das LineNumberReader-Objekt. */
    private final LineNumberReader lineReader;

    /** Hält fest, ob der Reader geschlossen wurde. */
    private boolean closed;

    /** Zeichensatz der einzulesenden Datei (z.B. "ISO-8859-1", "UTF-8"). */
    private final Charset charset;

    /**
     * Der Konstruktor aus einem File.
     *
     * @param file
     *            Zu öffnende Datei.
     * @throws IORuntimeException
     *             Falls die angegebene Datei nicht existiert, keine normale Datei ist oder eine
     *             unbekannte Kodierung vorliegt.
     */
    public FineFileReader(File file) {
        this(file.getAbsolutePath());
    }

    /**
     * Der Konstruktor aus einem Dateinamen.
     *
     * @param fileName
     *            Name der zu öffnenden Datei.
     * @throws IORuntimeException
     *             Falls die angegebene Datei nicht existiert, keine normale Datei ist oder eine
     *             unbekannte Kodierung vorliegt.
     */
    public FineFileReader(String fileName) {
        this(fileName, Charset.ISO_8859_1);
    }

    /**
     * Der Konstruktor aus einem File und einem Charset.
     *
     * @param file
     *            Zu öffnende Datei.
     * @param charset
     *            Zeichensatz der einzulesenden Datei.
     * @throws IORuntimeException
     *             Falls die angegebene Datei nicht existiert, keine normale Datei ist oder eine
     *             unbekannte Kodierung vorliegt.
     */
    public FineFileReader(File file, Charset charset) {
        this(file.getAbsolutePath(), charset);
    }

    /**
     * Der Konstruktor aus einem Dateinamen und einem Charset.
     *
     * @param fileName
     *            Name der zu öffnenden Datei.
     * @param charset
     *            Zeichensatz der einzulesenden Datei.
     * @throws IORuntimeException
     *             Falls die angegebene Datei nicht existiert, keine normale Datei ist oder eine
     *             unbekannte Kodierung vorliegt.
     */
    public FineFileReader(String fileName, Charset charset) {
        this.fileName = fileName;
        this.charset = charset;
        lineReader = openReader();
        closed = false;
    }

    /**
     * Bildet das Reader-Objekt. Hier werden die Ausnahmen behandelt und in Laufzeitausnahmen
     * umgewandelt.
     *
     * @return Das Reader-Objekt.
     * @throws IORuntimeException
     *             Wenn die Datei nicht gefunden wurde oder eine unbekannte Kodierung vorliegt.
     */
    private LineNumberReader openReader() {
        try {
            return tryToOpenReader();
        }
        catch (FileNotFoundException e) {
            throw new IORuntimeException("Die Eingabedatei '"
                    + fileName + "' wurde nicht gefunden. ("
                    + e.getMessage() + ")");
        }
        catch (UnsupportedEncodingException e) {
            throw new IORuntimeException("Bei der Erzeugung des "
                    + "InputStreamReaders für die Eingabedatei '"
                    + fileName
                    + "' wurde eine nicht unterstützte Kodierung verwendet. ("
                    + e.getMessage() + ")");
        }
    }

    /**
     * Bildet das Reader-Objekt.
     *
     * @return Das Reader-Objekt.
     * @throws FileNotFoundException
     *             Wenn die angegebene Datei nicht gefunden wurde.
     * @throws UnsupportedEncodingException
     *             Wenn eine unbekannte Kodierung für den InputStreamReader verwendet wurde.
     */
    private LineNumberReader tryToOpenReader() throws FileNotFoundException,
            UnsupportedEncodingException {
        InputStream inputStream = new FileInputStream(fileName);
        InputStreamReader reader = new InputStreamReader(inputStream, charset.getCharsetAsString());
        return new LineNumberReader(reader);
    }

    /** Erzeugt eine Stringrepräsentation des Objekts. */
    @Override
    public String toString() {
        return "FineFileReader[fileName:" + fileName + ", charset:" + charset.getCharsetAsString()
                + "]";
    }

    /**
     * Liest die nächste Zeile aus der Datei ein.
     *
     * @return Die nächste Zeile oder null, falls das Ende der Datei erreicht wurde.
     * @throws IORuntimeException
     *             Falls die Zeile nicht eingelesen werden konnte.
     */
    @Override
    public String readNextLine() {
        if (closed) {
            throw new IORuntimeException("Es wurde versucht, aus der geschlossenen Datei '"
                    + fileName + "' zu lesen");
        }
        else {
            try {
                return lineReader.readLine();
            }
            catch (IOException e) {
                throw new IORuntimeException("Es trat ein Fehler beim Einlesen der nächsten Zeile "
                        + "aus der Datei '" + fileName + "' auf. (" + e.getMessage() + ")");
            }
        }
    }

    /** Liefert die aktuelle Zeilennummer zurück. */
    @Override
    public int getLineNumber() {
        return lineReader.getLineNumber();
    }

    /**
     * Schließt den Reader.
     *
     * @throws IORuntimeException
     *             Wenn es beim Schließen zu Problemen kam.
     */
    @Override
    public void close() {
        if (closed) {
            throw new IORuntimeException("Es trat ein Fehler beim Schließen der Datei '"
                    + fileName + "' auf.");
        }
        else {
            tryToClose();
            closed = true;
        }
    }

    /**
     * Schließt den Reader.
     *
     * @throws IORuntimeException
     *             Wenn es beim Schließen zu Problemen kam.
     */
    private void tryToClose() {
        try {
            lineReader.close();
        }
        catch (IOException e) {
            throw new IORuntimeException("Es trat ein Fehler beim "
                    + "Schließen der Datei '" + fileName + "' auf. ("
                    + e.getMessage() + ")");
        }
    }

    /**
     * Gibt den Dateiinhalt (falls schon gelesen wurde: ab der momentanen Stelle) als Liste von
     * Strings zurück.
     *
     * @return Liste mit dem Dateiinhalt als Strings.
     */
    @Override
    public List readFileToListOfStrings() {
        List list = new ArrayList<>();

        String line = readNextLine();
        while (line != null) {
            list.add(line);
            line = readNextLine();
        }

        return list;
    }

    /**
     * Gibt den Dateiinhalt (falls schon gelesen wurde: ab der momentanen Stelle) als einen String
     * zurück.
     *
     * @return String mit dem Dateiinhalt.
     */
    @Override
    public String readFileToString() {
        StringBuilder builder = new StringBuilder();
        String lineSeparator = System.getProperty("line.separator");

        List list = readFileToListOfStrings();
        for (String line : list) {
            builder.append(line);
            builder.append(lineSeparator);
        }

        return builder.toString();
    }

    /** Liest eine tabgetrennte Zeile ein. */
    @Override
    public List readFieldsLine() {
        String line = readNextLine();
        if (null == line) {
            return null;
        }
        List fields = new ArrayList<>(Arrays.asList(line.split("\t", -1)));
        return fields;
    }

}

Charset

Charset

package de.duehl.basics.io;

/**
 * Enum für die Charsets.
 *
 * @see java.nio.charset.Charset
 *
 * @version 1.03     2016-10-14
 * @author Christian Dühl
 */

public enum Charset {

    US_ASCII(
            "US-ASCII",
            "Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode "
                    + "character set"),
    ISO_8859_1(
            "ISO-8859-1",
            "ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1"),
    UTF_8(
            "UTF-8",
            "Eight-bit UCS Transformation Format"),
    UTF_16BE(
            "UTF-16BE",
            "Sixteen-bit UCS Transformation Format, big-endian byte order"),
    UTF_16LE(
            "UTF-16LE",
            "Sixteen-bit UCS Transformation Format, little-endian byte order"),
    UTF_16(
            "UTF-16",
            "Sixteen-bit UCS Transformation Format, byte order identified by an optional "
                    + "byte-order mark"),
    ;

    // "Cp1252" ?

    private final String charsetAsString;
    private final String description;

    private Charset(String charsetAsString, String description) {
        this.charsetAsString = charsetAsString;
        this.description = description;
    }

    public String getCharsetAsString() {
        return charsetAsString;
    }

    public String getDescription() {
        return description;
    }

}

FileHelper

FileHelper

package de.duehl.basics.io;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.swing.filechooser.FileSystemView;

import de.duehl.basics.io.exceptions.DirectoryNotCreatedRuntimeException;
import de.duehl.basics.io.exceptions.FileNotFoundRuntimeException;
import de.duehl.basics.io.exceptions.IORuntimeException;

/**
 * Diese Klasse enthält Hilfsmethoden rund um das Dateisystem.
 *
 * @version 1.01     2016-10-14
 * @author Christian Dühl
 */

public class FileHelper {

    /** Eine Instanz soll hiervon nicht angelegt werden! */
    private FileHelper() {}

    /**
     * Löscht ein Verzeichnis mit Inhalt.
     *
     * @param path
     *            Verzeichnis
     * @throws IORuntimeException
     *             Wenn sich eine Datei oder Verzeichnis nicht löschen lässt.
     */
    public static void deleteTree(File path) {
        if (!path.exists()) {
            return;
        }
        for (File file : path.listFiles()) {
            if (file.isDirectory()) {
                deleteTree(file);
            }
            else if (!file.delete()) {
                throw new IORuntimeException(file + " could not be deleted!");
            }
        }

        if (!path.delete()) {
            throw new IORuntimeException(path + " could not be deleted!");
        }
    }

    /**
     * Löscht ein Verzeichnis mit Inhalt.
     *
     * @param path
     *            Verzeichnis
     * @throws IORuntimeException
     *             Wenn sich eine Datei oder Verzeichnis nicht löschen lässt.
     */
    public static void deleteTree(String path) {
        deleteTree(new File(path));
    }

    /**
     * Sucht alle Dateien mit einer bestimmten Endung in einem Verzeichnis und
     * seinen Unterverzeichnissen.
     *
     * @param start
     *            Verzeichnis, in dem die Suche beginnt.
     * @param extensions
     *            Liste aller Endungen der gesuchten Dateien (etwa ".txt" oder ".java")
     * @return Liste mit den gefundenen Dateien.
     */
    public static List findFiles(String start, String... extensions) {
        if (0 == extensions.length) {
            throw new IllegalArgumentException("Mindestens eine Endung muss angegebene werden.");
        }

        List lowerExtensions = new ArrayList<>();
        for (String extension : extensions) {
            lowerExtensions.add(extension.toLowerCase());
        }

        List files = new ArrayList<>();
        for (File file : new File(start).listFiles()) {
            String path = file.getPath();
            if (file.isDirectory()) {
                files.addAll(findFiles(path, extensions));
            }
            else {
                String lowerPath = path.toLowerCase();
                for (String lowerExtension : lowerExtensions) {
                    if (lowerPath.endsWith(lowerExtension)) {
                        files.add(path);
                    }
                }
            }
        }

        return files;
    }

    /**
     * Sucht alle Dateien mit einer bestimmten Endung in einem Verzeichnis ohne seine
     * Unterverzeichnisse zu berücksichtigen.
     *
     * @param start
     *            Verzeichnis, in dem die Suche beginnt.
     * @param extension
     *            Endung der gesuchten Dateien (etwa ".txt" oder ".java")
     * @return Liste mit den gefundenen Dateien.
     */
    public static List findFilesInMainDirectory(String start, String extension) {
        List files = new ArrayList<>();
        File startAsFile = new File(start);
        String lowerExtension = extension.toLowerCase();
        for (File file : startAsFile.listFiles()) {
            if (file.getPath().toLowerCase().endsWith(lowerExtension)) {
                files.add(file.getPath());
            }
        }
        return files;
    }

    /**
     * Sucht alle Dateien mit einer bestimmten Endung in einem Verzeichnis ohne seine
     * Unterverzeichnisse zu berücksichtigen.
     *
     * @param start
     *            Verzeichnis, in dem die Suche beginnt.
     * @param extension
     *            Endung der gesuchten Dateien (etwa ".txt" oder ".java")
     * @return Liste mit den gefundenen Dateien ohne Pfad.
     */
    public static List findFilesInMainDirectoryWithoutPath(String start, String extension) {
        List list = findFilesInMainDirectory(start, extension);
        List result = new ArrayList<>();
        for (String file : list) {
            String fileWithoutPath = getBareName(file);
            result.add(fileWithoutPath);
        }
        return result;
    }


    /**
     * Sucht alle Dateien in einem Verzeichnis ohne seine Unterverzeichnisse zu berücksichtigen.
     *
     * @param dir
     *            Verzeichnis, in dem die Suche beginnt.
     * @return Liste mit den gefundenen Dateien (mit Pfaden).
     */
    public static List findAllNormalFilesInMainDirectory(String dir) {
        List files = new ArrayList<>();
        File dirAsFile = new File(dir);
        for (File file : dirAsFile.listFiles()) {
            if (file.isFile()) {
                files.add(file.getPath());
            }
        }
        return files;
    }

    /**
     * Ermittelt, ob es mindestens eine Datei mit einer bestimmten Endung in einem Verzeichnis und
     * seinen Unterverzeichnissen gibt.
     *
     * @param start
     *            Verzeichnis, in dem die Suche beginnt.
     * @param extension
     *            Endung der gesuchten Dateien (etwa ".txt" oder ".java")
     * @return Liste mit den gefundenen Dateien.
     */
    public static boolean containsFiles(String start, String extension) {
        File startAsFile = new File(start);
        for (File file : startAsFile.listFiles()) {
            if (file.isDirectory()) {
                if (containsFiles(file.getPath(), extension)) {
                    return true;
                }
            }
            else {
                if (file.getPath().endsWith(extension)) {
                    // System.out.println("file " + file);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Ermittelt die Position des letzten Slash oder Backslash in einem Dateinamen.
     *
     * @param filename
     *            Zu untersuchender Dateiname.
     * @return Letzte Position (beginnend bei 0) oder -1, wenn weder Slash noch Backslash in der
     *         Eingabe enthalten waren.
     */
    public static int lastSlash(String filename) {
        int lastSlash = filename.lastIndexOf("/");
        int lastBackslash = filename.lastIndexOf("\\");
        if (lastSlash > lastBackslash) {
            return lastSlash;
        }
        else {
            return lastBackslash;
        }
    }

    /**
     * Normalisiert alle Backslashes zu Slashes.
     *
     * @param path
     *            Zu normalisierender Pfad.
     * @return Normalisierter Pfad.
     */
    public static String normalizeToSlahes(String path) {
        return path.replace("\\", "/");
    }

    /**
     * Normalisiert alle Slashes zu Backslashes.
     *
     * @param path
     *            Zu normalisierender Pfad.
     * @return Normalisierter Pfad.
     */
    public static String normalizeToBackSlahes(String path) {
        return path.replace("/", "\\");
    }

    /**
     * Ermittelt den Teil des übergebenen Dateinamens vor und inklusive des letzten Slashs oder
     * Backslashs.
     *
     * @param filename
     *            Zu untersuchender Dateiname.
     * @return Teil des Dateinamens vor dem letzten Slash oder Backslash inklusive dieses Zeichens.
     */
    public static String getDirName(String filename) {
        int index = lastSlash(filename);
        if (index == filename.length() - 1) {
            return getDirName(filename.substring(0, filename.length() - 1));
        }
        else {
            return filename.substring(0, index+1);
        }
    }

    /**
     * Ermittelt den Teil des übergebenen Dateinamens nach dem letzten Slash oder Backslash.
     *
     * @param filename
     *            Zu untersuchender Dateiname.
     * @return Teil des Dateinamens nach dem letzten Slash oder Backslash. Falls der String mit
     *         einem solchen Zeichen endet, wird ein leerer String zurückgegeben.
     */
    public static String getBareName(String filename) {
        int index = lastSlash(filename);
        String bareFileName;
        if (filename.length() > index+1) {
            bareFileName = filename.substring(index + 1);
        }
        else {
            bareFileName = "";
        }
        return bareFileName;

        // alternativ: (new File(fileName)).getName();
    }

    /**
     * Es wird der Pfad für ~/localDirectory zurückgegeben. Das Home-Verzeichnis wird dabei per
     * System.getProperty("user.home", ".") ermittelt. Falls es nicht existiert, wird es
     * angelegt.
     *
     * @param localDirectory
     *            Name des lokalen Verzeichnisses (etwa ".Jarify").
     * @return Pfad für ~/localDirectory.
     * @throws FileNotFoundRuntimeException
     *             Falls das Home-Verzeichnis nicht existiert.
     * @throws DirectoryNotCreatedRuntimeException
     *             Falls ~/localDirectory nicht existiert und nicht angelegt werden kann.
     */
    public static String getAndPerhapsCreateDirectoryAtHome(String localDirectory) {
        String home = homeDirectory();
        // TODO: createSubdirectoryInExistingDirectoryIfNecessary nutzen

        File homeDir   = new File(home);
        if (!homeDir.isDirectory()) {
            throw new FileNotFoundRuntimeException("Das Home-Verzeichnis '" + homeDir
                    + "' existiert nicht!");
        }

        File localPath = new File(home + File.separator + localDirectory);

        if (!localPath.isDirectory()) {
            boolean success = localPath.mkdir();
            if (!success) {
                throw new DirectoryNotCreatedRuntimeException("Das Verzeichnis " + localPath
                        + " kann nicht angelegt werden.");
            }
        }

        return localPath.getAbsolutePath();
    }

    /**
     * Es wird ein Unterverzeichnis in einem bestehenden Verzeichnis angelegt,
     * falls es noch nicht besteht.                                              

* * Im Beispiel mit dir = c:/temp und subDirWithoutPath = blubb wird das * Verzeichnis c:/temp/blubb angelegt, wenn es c:/temp gibt und * c:/temp/blubb noch nicht gibt. * * @param dir * Name des bestehenden, übergeordneten Verzeichnisses (etwa * "c:/temp"). * @param subDirWithoutPath * Name des unterverzeichnisses (ohne Pfad), das darunter * angelegt werden soll, etwa "blubb". * @throws FileNotFoundRuntimeException * Falls das Home-Verzeichnis nicht existiert. * @throws DirectoryNotCreatedRuntimeException * Falls ~/localDirectory nicht existiert und nicht angelegt * werden kann. */ public static void createSubdirectoryInExistingDirectoryIfNecessary(String dir, String subDirWithoutPath) { File directory = new File(dir); if (!directory.isDirectory()) { throw new FileNotFoundRuntimeException("Das Verzeichnis '" + dir + "' existiert nicht!"); } File subDirectory = new File(dir + File.separator + subDirWithoutPath); if (!subDirectory.isDirectory()) { boolean success = subDirectory.mkdir(); if (!success) { throw new DirectoryNotCreatedRuntimeException("Das Verzeichnis " + subDirectory + " kann nicht angelegt werden."); } } } /** * Legt ein Verzeichnis an. * * @param dirName * Name des Verzeichnisses. * @return true genau dann, wenn das Verzeichnis angelegt wurde. false anderenfalls. */ public static boolean createDirectory(String dirName) { File dir = new File(dirName); boolean success = dir.mkdir(); return success; } /** * Legt ein Verzeichnis an, falls es nicht vorhanden ist. * * @param dirName * Name des Verzeichnisses. */ public static void createDirectoryIfNotExists(String dirName) { if (!exists(dirName)) { createDirectory(dirName); } } /** * Ermittelt das Home-Directory (~ unter Linux, c:\Users\UserName unter * Windows). * * @return Home-Verzeichnis. */ public static String homeDirectory() { String home = System.getProperty("user.home", "."); return home; } /** * Kopiert eine einzelne Datei. * * @param source * Quelldatei * @param target * Zieldatei * @throws IORuntimeException * Falls etwas beim Kopieren schief geht. */ public static void copyFile(String source, String target) { Path sourcePath = Paths.get(source); Path targetPath = Paths.get(target); try { Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { throw new IORuntimeException(e); } } /** * Kopiert eine einzelne Datei. * * @param source * Quelldatei * @param target * Zieldatei * @throws IORuntimeException * Falls etwas beim Kopieren schief geht. */ public static void copyFile(File source, File target) { copyFile(source.getAbsolutePath(), target.getAbsolutePath()); } /** * Prüft, ob die Datei mit dem gegebenen Dateinamen existiert. * * @param filename * Name der Datei. * @return Wahrheitswert. */ public static boolean exists(String filename) { File file = new File(filename); return file.exists(); } /** * Prüft, ob die Datei mit dem gegebenen Dateinamen existiert. * * @param filename * Name der Datei. * @return Wahrheitswert. */ public static boolean isFile(String filename) { File file = new File(filename); return file.isFile(); } /** * Prüft, ob das Verzeichnis mit dem gegebenen Dateinamen existiert und ein Verzeichnis ist. * * @param dir * Name des Verzeichnisses. * @return Wahrheitswert. */ public static boolean isDirectory(String dir) { File file = new File(dir); return file.isDirectory(); } /** * Prüft, ob das Verzeichnis mit dem gegebenen Dateinamen nicht existiert oder kein Verzeichnis * ist. * * @param dir * Name des Verzeichnisses. * @return Wahrheitswert. */ public static boolean isNotADirectory(String dir) { return !isDirectory(dir); } /** * Verschiebt eine einzelne Datei (mit Hilfe von copyFile() und deleteFile()). * * @param source * Quelldatei * @param target * Zieldatei * @throws IORuntimeException * Falls etwas beim Kopieren schief geht. */ public static void moveFile(String source, String target) { copyFile(source, target); deleteFile(source); } /** * Verschiebt eine einzelne Datei (mit Hilfe von copyFile() und deleteFile()). * * @param source * Quelldatei * @param target * Zieldatei * @throws IORuntimeException * Falls etwas beim Kopieren schief geht. */ public static void moveFile(File source, File target) { moveFile(source.getAbsolutePath(), target.getAbsolutePath()); } /** * Löscht eine Datei. * * @param fileName * Zu löschende Datei. * @throws IORuntimeException * Falls sich die Datei nicht löschen lässt. */ public static void deleteFile(String fileName) { File file = new File(fileName); if (!file.delete()) { throw new IORuntimeException(file + " could not be deleted!"); } } /** * Löscht eine Datei, falls sie existiert. * * @param fileName * Zu löschende Datei. * @throws IORuntimeException * Falls sich die Datei nicht löschen lässt. */ public static void deleteFileIfExistent(String fileName) { if (exists(fileName)) { deleteFile(fileName); } } /** * Legt eine Datei leer an. Wenn es sie schon gibt, wird sie leer überschrieben. * * @param fileName * Name der Datei. */ public static void createEmptyFile(String fileName) { FineFileWriter writer = new FineFileWriter(fileName); writer.close(); } /** * Liest den Inhalt der Datei mit dem gegebenen Dateinamen in einen String und gibt diese * zurück. * * @param filename * Name der Datei. * @return Inhalt der Datei. */ public static String readFileToString(String filename) { Reader reader = new FineFileReader(filename); String contents = reader.readFileToString(); reader.close(); return contents; } /** * Liest den Inhalt der Datei im angegebenen Encoding mit dem gegebenen Dateinamen in einen * String und gibt diese zurück. * * @param filename * Name der Datei. * @param charset * Encoding der Datei. * @return Inhalt der Datei. */ public static String readFileToString(String filename, Charset charset) { Reader reader = new FineFileReader(filename, charset); String contents = reader.readFileToString(); reader.close(); return contents; } /** * Liest den Inhalt der Datei mit dem gegebenen Dateinamen in einen String und gibt diese * zurück. * * @param file * Datei. * @return Inhalt der Datei. */ public static String readFileToString(File file) { return readFileToString(file.getPath()); } /** * Liest den Inhalt der Datei mit dem gegebenen Dateinamen in eine Liste seiner Zeilen und gibt * diese zurück. * * @param filename * Name der Datei. * @return Inhalt der Datei als Liste der Zeilen. */ public static List readFileToList(String filename) { return readFromReaderToList(new FineFileReader(filename)); } /** * Liest die Zeilen aus dem übergebenen Reader in eine Liste ein und schließt den Reader dann. * * @param reader * Zu verwendender Reader. * @return Liste mit den Zeilen. */ private static List readFromReaderToList(Reader reader) { List contents = reader.readFileToListOfStrings(); reader.close(); return contents; } /** * Liest den Inhalt der Datei mit dem gegebenen Dateinamen in eine Liste * seiner Zeilen, wobei leere Zeilen und solche, die mit '#' anfangen, * übersprungen werden.

* * Die Zeilen werden nicht um vorn oder hinten befindliche Leerzeichen * bereinigt. * * @param filename * Name der Datei. * @return Inhalt der Datei ohne Leerzeilen und Kommentare als Liste der Zeilen. */ public static List readFileToListIgnoreBlankAndCommentLines(String filename) { List list = new ArrayList<>(); Reader reader = new FineFileReader(filename); String line; while (null != (line = reader.readNextLine())) { String testLine = line.trim(); if (!testLine.isEmpty() && !testLine.startsWith("#")) { list.add(line); } } return list; } /** * Liest den Inhalt der Datei mit dem gegebenen Dateinamen in eine Liste seiner Zeilen und gibt * diese zurück. * * @param filename * Name der Datei. * @param charset * Encoding der Datei. * @return Inhalt der Datei als Liste der Zeilen. */ public static List readFileToList(String filename, Charset charset) { return readFromReaderToList(new FineFileReader(filename, charset)); } /** * Speichert eine Datei als Sicherheitskopie ab. Der Name wird dabei automatisch erzeugt. * * @param originalFileName * Name der Originaldatei, die gesichert werden soll. */ public static void backupFile(String originalFileName) { File originalFile = new File(originalFileName); if (originalFile.exists()) { long lastModified = originalFile.lastModified(); GregorianCalendar cal = new GregorianCalendar(); cal.setTime(new Date(lastModified)); String insertion = String.format("_%1$tY%1$tm%1$td", cal); String backupFileName = insertBeforeExtension(originalFileName, insertion); copyFile(originalFileName, backupFileName); } } /** * Fügt einen String in einen Dateinamen vor den Punkt und die Erweiterung. Also wird aus * "/user/bla/datei.txt" und "_foo" dann ein "/user/bla/datei_foo.txt". * * @param originalFileName * Der Ausgangsname. * @param insertion * Der einzufügende Teil. * @return Name mit eingefügtem Text. */ public static String insertBeforeExtension(String originalFileName, String insertion) { String dir = FileHelper.getDirName(originalFileName); String bareName = FileHelper.getBareName(originalFileName); int lastPointIndex = bareName.lastIndexOf("."); String newBareName; if (lastPointIndex > -1) { String beforePoint = bareName.substring(0, lastPointIndex); String pointAndAfter = bareName.substring(lastPointIndex); newBareName = beforePoint + insertion + pointAndAfter; } else { newBareName = bareName + insertion; } if (dir.isEmpty()) { return newBareName; } else { return concatPathes(dir, newBareName); } } /** * Speichert einen String in eine Datei. * * @param text * Der zu speichernde String. * @param fileName * Der Name der zu erzeugenden Datei. */ public static void writeTextToFile(String text, String fileName) { FineFileWriter writer = new FineFileWriter(fileName); writer.writeln(text); writer.close(); } /** * Speichert einen String in eine Datei mit aktuellem Datum und Zeit als Einschub vor die * Erweiterung. * * @param text * Der zu speichernde String. * @param front * Der vordere Teil des Namens der zu erzeugenden Datei. * @param rear * Der hintere Teil des Namens der zu erzeugenden Datei. */ public static void writeTextToFileWithDate(String text, String front, String rear) { GregorianCalendar cal = new GregorianCalendar(); String insertion = String.format("%1$tY%1$tm%1$td_%1$tH%1$tM%1$tS", cal); writeTextToFile(text, front + insertion + rear); } /** * Schreibt die Liste mit den Zeilen in die Datei mit dem angegebenen Namen. * * @param lines * Die Liste mit den auszugebenden Zeilen. * @param filename * Name der zu erzeugenden Datei. */ public static void writeLinesToFile(List lines, String filename) { writeLinesToWriter(new FineFileWriter(filename), lines); } /** * Schreibt die Liste mit den Zeilen unter Verwendung des angegebenen Encodings in die Datei * mit dem angegebenen Namen. * * @param lines * Die Liste mit den auszugebenden Zeilen. * @param filename * Name der zu erzeugenden Datei. * @param charset * Encoding der Datei. */ public static void writeLinesToFile(List lines, String filename, Charset charset) { writeLinesToWriter(new FineFileWriter(filename, charset), lines); } /** * Schreibt die Zeilen auf den angegebenen Writer und schließt diesen dann. * * @param writer * Zu verwendender Writer. * @param lines * Auszugebende Zeilen. */ private static void writeLinesToWriter(FineFileWriter writer, List lines) { writer.writeAllLines(lines); writer.close(); } /** * Fügt den angegebenen Text und einen Zeilenumbruch an die angegebene Datei an. * * @param text * Anzufügender Text. * @param fileName * Dateiname */ public static void addTextToFile(String text, String fileName) { FineFileWriter writer = new FineFileWriter(fileName, true); writer.writeln(text); writer.close(); } /** * Verschiebt eine Datei (mit Hilfe von {@link File#renameTo(File)}). * * @param source * Die Datei, die kopiert werden soll. * @param target * Die Datei, die erstellt und geschrieben wird. * @return Erfolg */ public static boolean moveFileByRenameTo(String source, String target) { if (source.equals(target)) { return false; } File sourceFile = new File(source); File targetFile = new File(target); return sourceFile.renameTo(targetFile); } /** * Kopiert den Text aus einer Datei in eine andere. * * @param source * Die Datei, die kopiert werden soll. * @param target * Die Datei, die erstellt und geschrieben wird. */ public static void copyTextFileByReadAndWrite(String source, String target) { if (source.equals(target)) { return; } Reader reader = new FineFileReader(source); Writer writer = new FineFileWriter(target); while (true) { String line = reader.readNextLine(); if (null == line) { break; } writer.writeln(line); } writer.close(); reader.close(); } /** * Setzt zwei Pfade so zusammen, dass sowohl doppelte als auch fehlende Trenner vermieden * werden. * * @param part1 * Erster Teil des Pfades. * @param part2 * Zweiter Teil des Pfades. * @return Zusammengesetzter Pfad. */ public static String concatPathes(String part1, String part2) { boolean endsWithSlash = part1.endsWith("/") || part1.endsWith("\\"); boolean startsWithSlash = part2.startsWith("/") || part2.startsWith("\\"); if (endsWithSlash && startsWithSlash) { String tmp = part1.substring(0, part1.length() - 1); return tmp + part2; } else if (endsWithSlash || startsWithSlash) { return part1 + part2; } else { return part1 + File.separator + part2; } } /** * Setzt zwei Pfade so zusammen, dass sowohl doppelte als auch fehlende Trenner vermieden * werden. * * @param part1 * Erster Teil des Pfades. * @param part2 * Zweiter Teil des Pfades. * @return Zusammengesetzter Pfad. */ public static String concatPathes(File part1, String part2) { return concatPathes(part1.getPath(), part2); } /** * Setzt zwei Pfade so zusammen, dass sowohl doppelte als auch fehlende Trenner vermieden * werden. * * @param part1 * Erster Teil des Pfades. * @param part2 * Zweiter Teil des Pfades. * @return Zusammengesetzter Pfad. */ public static String concatPathes(String part1, File part2) { return concatPathes(part1, part2.getPath()); /* * Macht das Sinn? Dann würde man an irgendwas einen kompletten Pfad dranhängen, vermutlich * nicht! Momentan wird die Methode auch nicht genutzt. */ } /** * Setzt zwei Pfade so zusammen, dass sowohl doppelte als auch fehlende Trenner vermieden * werden. * * @param part1 * Erster Teil des Pfades. * @param part2 * Zweiter Teil des Pfades. * @return Zusammengesetzter Pfad. */ public static String concatPathes(File part1, File part2) { return concatPathes(part1.getPath(), part2.getPath()); /* * Macht das Sinn? Dann würde man an einen kompletten Pfad einen kompletten Pfad * dranhängen, vermutlich nicht! Momentan wird die Methode auch nicht genutzt. */ } /** * Setzt mehrere Pfadstücke so zusammen, dass sowohl doppelte als auch fehlende Trenner * vermieden werden. * * @param parts * Teile des Pfades * @return Zusammengesetzter Pfad. */ public static String concatPathesMultiple(String ... parts) { if (parts.length == 0) { return ""; } else if (parts.length == 1) { return parts[0]; } String filename = parts[0]; for (int index = 1; index < parts.length; ++index) { filename = concatPathes(filename, parts[index]); } return filename; } /** * Erzeugt aus einer Zeile der Art

     * "DokNr";"Vortext"

* eine Liste mit den einzelnen Werten. * * @param line * Eingelesene Zeile. * @return Liste mit den Werten der Zeile. */ public static List splitCsvSemikolonLine(String line) { if (!line.startsWith("\"")) { throw new IllegalArgumentException("Die zum Aufsplitten übergebene Zeile beginnt " + "nicht mit einem Anführungzeichen!\n\tZeile: " + line); } if (!line.endsWith("\"")) { throw new IllegalArgumentException("Die zum Aufsplitten übergebene Zeile wird nicht " + "von einem Anführungzeichen beendet!\n\tZeile: " + line); } /* Vorderes und hinteres Anführungszeichen abschneiden: */ String shortLine = line.substring(1, line.length() - 1); return Arrays.asList(shortLine.split("\";\"", -1)); } /** * Ermittelt alle Dateien in einem Verzeichnis, die einem bestimmten Kriterium entsprechen. * * @param source * Verzeichnis, in dem gesucht wird. * @param filenameFilter * Kriterium an den Dateinamen der zu suchenden Dateien. * @return Liste mit allen passenden Dateien. */ public static List searchDir(File source, FilenameFilter filenameFilter) { List files = new ArrayList<>(); for (File file : source.listFiles(filenameFilter)) { files.add(file.getPath()); } return files; } /** * Ermittelt den letzten Zeitpunkt der Modifikation einer Datei. * * @param filename * Name der Datei. * @return Zeitpunkt im Timestamp-Format YYYYMMDD_HHMMSS. */ public static String fileLastModified(String filename) { return fileLastModified(new File(filename)); } /** * Ermittelt den letzten Zeitpunkt der Modifikation einer Datei. * * @param file * Zu untersuchende Datei. * @return Zeitpunkt im Timestamp-Format YYYYMMDD_HHMMSS. */ public static String fileLastModified(File file) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); return sdf.format(file.lastModified()); } /** * Stellt fest, ob das angegebenen Verzeichnis leer ist. * * @param dir * Zu überprüfendes Verzeichnis, muss existieren. * @return Wahrheitswert: true genau dann, wenn das Verzeichnis leer ist. */ public static boolean isDirectoryEmpty(String dir) { File dirAsFile = new File(dir); int numberOfFoundFiles = dirAsFile.listFiles().length; return 0 == numberOfFoundFiles; } /** * Stellt fest, ob das angegebenen Verzeichnis Unterverzeichnisse enthält. * * @param dir * Zu überprüfendes Verzeichnis, muss existieren. * @return Wahrheitswert: true genau dann, wenn das Verzeichnis Unterverzeichnisse enthält. */ public static boolean hasDirectorySubdirectories(String dir) { if (!isDirectory(dir)) { return false; } File dirAsFile = new File(dir); for (File file : dirAsFile.listFiles()) { if (file.isDirectory()) { return true; } } return false; } /** * Erstellt ein leere Datei im Default-Verzeichnis für temporäre Dateien, die mit dem Prefix * beginnt und mit dem Suffix endet. * * @param prefix * Prefix mit dem der Dateiname beginnt. Muss mindestens drei Zeichen lang sein. * @param suffix * Suffix auf den der Dateiname endet. * @return File-Objekt mit der erstellten Datei. * @throws IORuntimeException * Falls etwas dabei schief geht. */ public static File createTempFile(String prefix, String suffix) { try { return File.createTempFile(prefix, suffix); } catch (IOException e) { throw new IORuntimeException(e); } } /** * Entfernt . und .. aus Dateinamen. * * @param filename * Dateiname. * @return normalisierter Dateiname. */ public static String normalisePath(String filename) { try { File file = new File(filename); return file.getCanonicalPath(); } catch (IOException e) { throw new IORuntimeException(e); } } /** * Ermittelt die Laufwerksbezeichnung zu einer beliebigen Datei oder einem Verzeichnis. * * @param path * Dateiname oder Verzeichnisname mit vollem Pfad. * @return Laufwerksbezeichnung * @throws RuntimeException * Falls path nicht existiert oder zu path die Laufwerksbezeichnung nicht ermittelt * werden konnte (z.B. wenn path nicht mit "R:\\" oder "r:\\" oder so beginnt, * sondern mit "R:/" (hier hilft normalizeToBackSlashes()) oder * "\\Cluster1\Projekte1"). */ public static String getSystemDisplayName(String path) { File file = new File(path); if (!file.exists()) { throw new RuntimeException("Die Datei oder das Verzeichnis '" + path + "' existiert nicht!"); } FileSystemView fsv = FileSystemView.getFileSystemView(); String upperCasePath = path.toUpperCase(); for (File rootAsFile : File.listRoots()) { String root = rootAsFile.getPath(); String upperCaseRoot = root.toUpperCase(); if (upperCasePath.startsWith(upperCaseRoot)) { String displayName = fsv.getSystemDisplayName(rootAsFile); if (displayName.matches(".* \\([A-Z]:\\)")) { displayName = displayName.substring(0, displayName.length() - 5); } return displayName; } } throw new RuntimeException("Zur Datei oder das Verzeichnis '" + path + "' konnte die Laufwerksbezeichnung nicht ermittelt werden!"); } }

Nachwort

Die unzähligen Tests führe ich an dieser Stelle nicht auf. Zu diesen gehören auch Testdateisysteme, das würde den Umfang hier sprengen.

Außerdem gehören noch selbst geschriebene Ausnahmen dazu, die die checked exceptions ersetzen. Exemplarisch hier die FileNotFoundException:

FileNotFoundRuntimeException

package de.duehl.basics.io.exceptions;

import java.io.FileNotFoundException;

/**
 * Ausnahmeklasse, die statt einer FileNotFoundException eine
 * FileNotFoundRuntimeException darstellt.
 *
 * @version 1.01     2013-12-12
 * @author Christian Dühl
 */

public class FileNotFoundRuntimeException extends RuntimeException {

    private static final long serialVersionUID = 2795730444012714039L;

    /** Konstruktor */
    public FileNotFoundRuntimeException() {
        super();
    }

    /**
     * Konstruktor
     *
     * @param message
     *            Text der Fehlermeldung.
     */
    public FileNotFoundRuntimeException(String message) {
        super(message);
    }

    /**
     * Konstruktor
     *
     * @param exception
     *            Die FileNotFoundException, die nun in Form einer
     *            RuntimeException verpackt werden soll.
     */
    public FileNotFoundRuntimeException(FileNotFoundException exception) {
        super(exception);
    }

}

zu meiner Javaseite zu meiner Javaseite

zur Startseite des Servers zur Startseite des Servers

Impressum

Valid CSS! Valid XHTML 1.0!

TOP Zum Seitenanfang

zuletzt geändert: