Verzeichnisse durchsuchen/bearbeiten/auslesen (Java)

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen

Ein Verzeichnis auslesen

Um ein Verzeichnis auszulesen stellt das Java-API schon die Methode listFiles() bzw. list() in der Klasse java.io.File bereit:

File f = new File("C:/Programme");
File[] fileArray = f.listFiles();

Zurückgeliefert wird von listFiles() ein File-Array und von list() ein String-Array in welchem alle Dateien und Ordner in diesem Verzeichnis gespeichert werden. Damit lässt sich schon eine einfache Methode schreiben, mit welcher der Inhalt eines Verzeichnisses ausgegeben werden kann. Hilfreich ist noch die Methode File#isDirectory() mit welcher getestet wird ob das File auf einen Ordner verweist. Wichtig ist noch zu überprüfen ob das File-Array nichtgleich null ist, da z. B. bei nicht ausreichenden Berechtigungen um auf einen Ordnern zuzugreifen listFiles() null zurückliefert.

public void listDir(File dir) {

	File[] files = dir.listFiles();
	if (files != null) { // Erforderliche Berechtigungen etc. sind vorhanden
		for (int i = 0; i < files.length; i++) {
			System.out.print(files[i].getAbsolutePath());
			if (files[i].isDirectory()) {
				System.out.print(" (Ordner)\n");
			}
			else {
				System.out.print(" (Datei)\n");
			}
		}
	}
}

Leider gibt diese Methode nicht den Inhalt der evtl. vorhandenen Unterverzeichnisse aus. Dieses Problem lässt sich aber ganz einfach mit einer rekursiven Methode beheben.

public void listDir(File dir) {

	File[] files = dir.listFiles();
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
			System.out.print(files[i].getAbsolutePath());
			if (files[i].isDirectory()) {
				System.out.print(" (Ordner)\n");
				listDir(files[i]); // ruft sich selbst mit dem 
					// Unterverzeichnis als Parameter auf
			}
			else {
				System.out.print(" (Datei)\n");
			}
		}
	}
}

Eine Datei auslesen

In Java 7 kamen neue Hilfsklassen hinzu, die ein einfacheres Auslesen von Dateien ermöglichen:

List<String> lines =  Files.readAllLines(FileSystems.getDefault().getPath("Text.txt"), StandardCharsets.UTF_8);          
for (String line : lines) {
     System.out.println(line);
}

Eine ZIP-Datei transparent innerhalb des Dateisystems verwenden

Inhalte von gepackten Archiven lassen sich auch seit Java 7 direkt im Dateisystem darstellen.

Path zipfile = Paths.get("/beispiele/zipfs/archiv.zip");
FileSystem fs = FileSystems.newFileSystem(zipfile, env, null);

Ein Verzeichnis durchsuchen

Prinzipiell ist es jetzt nicht mehr schwer aus der rekursiven Auflistung eine Suche zu basteln. Es muss nur noch ein Parameter mehr übergeben werden (nämlich der Dateiname nach welchem gesucht werden soll) und es wird ein Rückgabetyp benötigt in welchem die Treffer gespeichert werden.

public ArrayList<File> searchFile(File dir, String find) {

	File[] files = dir.listFiles();
	ArrayList<File> matches = new ArrayList<File> ();
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
			if (files[i].getName().equalsIgnoreCase(find)) { // überprüft ob der Dateiname mit dem Suchstring
									 // übereinstimmt. Groß-/Kleinschreibung wird
									 // ignoriert.
				matches.add(files[i]);
			}
			if (files[i].isDirectory()) {
				matches.addAll(searchFile(files[i], find)); // fügt der ArrayList die ArrayList mit den
									    // Treffern aus dem Unterordner hinzu
			}
		}
	}
	return matches;
}

Da es mehrere Möglichkeiten gibt, wie man nach einer Datei suchen kann (String ist im Dateinamen enthalten, Datei fängt mit String an, Datei hört mit String auf, ...) beschränkt sich diese Methode auf die Überprüfung, ob die Dateien (abgesehen von der Groß- und Kleinschreibung) exakt übereinstimmen und gilt somit eher als Vorlage für eine eigene Dateisuche.

Ein Verzeichnis löschen

Mit der Methode File#delete() kann man eine Datei oder einen Ordner löschen. Zu beachten sind folgende Punkte:

  1. Nur leere Verzeichnisse können gelöscht werden
  2. Unter Umständen kann eine Datei nicht gelöscht werden (Schreibschutz, Datei wird gerade verwendet und ist deshalb gesperrt, ...). Sollte dies der Fall sein liefert delete() false zurück.
public void deleteDir(File dir) {

	File[] files = dir.listFiles();
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				deleteDir(files[i]); // Verzeichnis leeren und anschließend löschen
			}
			else {
				files[i].delete(); // Datei löschen
			}
		}
		dir.delete(); // Ordner löschen
	}
}

Ein Verzeichnis kopieren

Auch hierfür muss die Methode natürlich nur geringfügig angepasst werden. Es wird nun das Quell- und Zielverzeichnis mitübergeben. Wie gewohnt werden alle Dateien und Ordner in einem File-Array gespeichert. Zusätzlich wird ein File-Objekt benötigt welches den neuen Zielpfad anhand des Quellpfades für jede Datei/jeden Ordner bestimmt. Mittels File#mkdirs() wird das Zielverzeichnis inkl. allen benötigten ßberordnern (sofern noch nicht vorhanden) neu angelegt.

public void copyDir(File quelle, File ziel) throws FileNotFoundException, IOException {
		
	File[] files = quelle.listFiles();
	File newFile = null; // in diesem Objekt wird für jedes File der Zielpfad gespeichert.
			     // 1. Der alte Zielpfad
			     // 2. Das systemspezifische Pfadtrennungszeichen
			     // 3. Der Name des aktuellen Ordners/der aktuellen Datei
	ziel.mkdirs();	     // erstellt alle benötigten Ordner
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
				newFile = new File(ziel.getAbsolutePath() + System.getProperty("file.separator") + files[i].getName());
			if (files[i].isDirectory()) {
				copyDir(files[i], newFile);
			}
			else {
				copyFile(files[i], newFile);
			}
		}
	}
}

Die Methode copyFile(File quelle, File ziel) welche das eigentliche Kopieren mithilfe eines BufferedInputStreams und eines BufferedOutputStreams übernimmt schaut wie folgt aus:

public void copyFile(File file, File ziel) throws FileNotFoundException, IOException {
		
	BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
	BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(ziel, true));
	int bytes = 0;
	while ((bytes = in.read()) != -1) { // Datei einlesen
		out.write(bytes); // Datei schreiben
	}
	in.close();
	out.close();
}


Größe eines Verzeichnisses bestimmen

Auch hier muss die Sache wieder rekursiv angegangen werden. Mit File#length() bekommt man die Größe der Datei in byte als long zurückgeliefert.

public long getDirSize(File dir) {
		
	long size = 0;
	File[] files = dir.listFiles();
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				size += getDirSize(files[i]); // Gesamtgröße des Verzeichnisses aufaddieren
			}
			else {
				size += files[i].length(); // Größe der Datei aufaddieren
			}
		}
	}
	return size;
}

Ein Verzeichnis auf Veränderungen überwachen

Oracle - Watching a Directory for Changes

Allgemeine Klasse (komplettes Beispiel)

Hier noch mal alle Methoden in einer Klasse "vereint":

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class DirEdit {

	public void copyDir(File quelle, File ziel) throws FileNotFoundException, IOException {
		
		File[] files = quelle.listFiles();
		File newFile = null;
		ziel.mkdirs();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				newFile = new File(ziel.getAbsolutePath() + System.getProperty("file.separator") + files[i].getName());
				if (files[i].isDirectory()) {
					copyDir(files[i], newFile);
				}
				else {
					copyFile(files[i], newFile);
				}
			}
		}
	}
	
	public void copyFile(File file, File ziel) throws FileNotFoundException, IOException {
		
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(ziel, true));
		int bytes = 0;
		while ((bytes = in.read()) != -1) {
			out.write(bytes);
		}
		in.close();
		out.close();
	}

	public void deleteDir(File dir) {

		File[] files = dir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					deleteDir(files[i]);
				}
				else {
					files[i].delete();
				}
			}
			dir.delete();
		}
	}
	
	public ArrayList<File> searchFile(File dir, String find) {

		File[] files = dir.listFiles();
		ArrayList<File> matches = new ArrayList<File> ();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].getName().equalsIgnoreCase(find)) { 
					matches.add(files[i]);
				}
				if (files[i].isDirectory()) {
					matches.addAll(searchFile(files[i], find)); 
				}
			}
		}
		return matches;
	}
	
	public void listDir(File dir) {

		File[] files = dir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				System.out.print(files[i].getAbsolutePath());
				if (files[i].isDirectory()) {
					System.out.print(" (Ordner)\n");
					listDir(files[i]); 
				}
				else {
					System.out.print(" (Datei)\n");
				}
			}
		}
	}
	
	public long getDirSize(File dir) {
		
		long size = 0;
		File[] files = dir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					size += getDirSize(files[i]);
				}
				else {
					size += files[i].length();
				}
			}
		}
		return size;
	}
}


Fragen

Das Thema wurde nicht ausreichend behandelt? Du hast Fragen dazu und brauchst weitere Informationen? Lass Dir von uns helfen!

Wir helfen dir gerne!


Dir hat dieser Artikel gefallen? Oder Du hast Fehler entdeckt und möchtest zur Berichtigung beitragen? Prima! Schreibe einen Kommentar!

Du musst angemeldet sein, um einen Kommentar abzugeben.


Quellen und weiterführende Links

--The_S (08.08.2006, 21:07 Uhr)