Dateisystem
Eintrag zuletzt aktualisiert am: 24.05.2022
Für die Arbeit mit dem Dateisystem stellt das
.NET Framework Klassen im Namensraum
System.IO bereit. Bei
WinRT gibt es eigenen Klassen in Windows.
Storage.FileIO.
Programmierung mit System.IO
Im Mittelpunkt der Programmierung des Dateisystems stehen die Klassen DriveInfo (Laufwerk), Direc¬toryInfo (Verzeichnis) und FileInfo (Datei). Die entsprechenden
Objektmengen werden in Arrays des jeweiligen
Objekttyps verwaltet; eigene Mengenklassen existieren im Gegensatz zu vielen anderen Anwendungsbereichen in der
FCL nicht. Die Klasse DriveInfo ist neu seit
.NET 2.0.
Neben DirectoryInfo und FileInfo bietet die
FCL alternativ für den Zugriff auf Verzeichnisse und Dateien auch die Klassen File und Directory an. Letztgenannte besitzen nur statische Mitglieder mit Dateisystemoperationen wie Copy(), Delete(), Move(), Open() und GetCreationTime(). Grundsätzlich bieten die beiden Klassenpaare äquivalente Funktionen in unterschiedlichen Darreichungsformen an. Für viele Anwendungen interessant ist Directory.GetCurrentDirectory(): Diese
Methode liefert das aktuelle Arbeitsverzeichnis einer Anwendung.
Beispiel 1: Liste der Laufwerke
Das erste Beispiel zeigt, wie Sie alle Laufwerke in Ihrem
Computersystem mit den zugehörigen Wurzel-verzeichnissen auflisten können.
public void Laufwerke_Auflisten()
{
foreach (DriveInfo di in DriveInfo.GetDrives())
{
Demo.Print("Laufwerk: " + di.Name);
if (di.IsReady)
{
Demo.Print(" Bezeichnung: " + di.Volume
Label);
Demo.Print(" Typ: " + di.DriveType);
Demo.Print(" Format: " + di.DriveFormat);
Demo.Print(" Größe: " + di.TotalSize);
Demo.Print(" Freier Platz: " + di.TotalFreeSpace);
Demo.Print(" Wurzelordner: " + di.RootDirectory.FullName);
}
else
{
Demo.Print(" ist nicht bereit!");
}
}
Listing 1:
Liste der Laufwerke ausgeben [
System.IO.Demo.cs]
Beispiel 2: Liste der Dateien in einem Verzeichnis
Das zweite Listing nimmt Zugriff auf das Verzeichnis /_Daten/Dateisystem unterhalb des aktuellen Ar-beitsverzeichnisses. Zunächst gibt die Routine Informationen über das Verzeichnis aus, dann listet sie alle in dem Verzeichnis enthaltenen Textdateien auf, indem sie GetFiles() mit dem Muster *.txt aufruft.
public void Datei_
Liste() {
//
Liste der Dateien in einem bestimmten Ordner
string verzeichnis = Directory.GetCurrentDirectory() + @"\_daten\dateisystem\";
// Zugriff auf ein Dateiverzeichnis
DirectoryInfo d = new DirectoryInfo(verzeichnis);
// Prüfung auf Existenz des Verzeichnisses
if ( !d.Exists ) {
Demo.Print("Verzeichnis nicht vorhanden!");
return;
}
// Ausgabe von Informationen über den Ordner
Demo.Print("Erzeugt am: " + d.CreationTime);
Demo.Print("Zuletzt gelesen am : " + d.LastAccessTime);
Demo.Print("Zuletzt geändert am : " + d.LastWriteTime);
Demo.Print("Wurzelordner: " + d.Root.Name);
Demo.Print("Name des übergeordneten Ordners: " + d.Parent.Name);
Demo.Print("Pfad des übergeordneten Ordners: " + d.Parent.FullName);
//
Liste aller Textdateien in diesem Verzeichnis
Demo.Print("Alle Textdateien in Ordner: " + d.FullName);
foreach (FileInfo f in d.GetFiles("*.txt"))
Demo.Print(f.Name + ";" + f.Length + ";" + f.CreationTime);
}
Listing 2:
Liste der Dateien in einem Verzeichnis ausgeben [
System.IO.Demo.cs]
HINWEIS: Leider fehlt in .NET nach wie vor sowohl in der Directory- als auch in der DirectoryInfo-Klasse eine
Methode zum Kopieren eines ganzen Verzeichnisses.
Die neue Möglichkeit EnumerateFiles() erlaubt mit
LINQ (ein kleiner Vorgriff auf Kapitel 10!) einfache Abfragen, welche sich auf Dateien sowie Dateiinhalte beziehen. Die
LINQ-Abfrage in Listing 3 ermittelt mit diesen
Methoden beispielsweise jene Zeilen aus sämtlichen
CSV-Dateien des aktuellen Ordners, bei welchen sich in der ersten Spalte der Wert 1 wiederfindet. Das Ergebnis dieser Abfrage – ein Ienumerable<string> – wird anschließend an die zuvor erwähnte
Methode WriteAllLines() übergeben, um die gefundenen Zeilen in der Datei result.txt zu hinterlegen.
DirectoryInfo dir = new DirectoryInfo("d:\datenordner");
var info =
from file in Directory.EnumerateFiles(".", "*.csv")
from line in File.ReadLines(file)
where line.Split(‘;’)[0] == "1"
select file + ": " + line;
File.WriteAllLines("result.txt", info);
Listing 3:
LINQ-Abfrage über sämtliche
CSV-Dateien eines Ordners
Dateiinhalte
Ähnlich wie
Java arbeitet .NET mit
Streams, um Inhalte von Dateien zu lesen und zu ändern. Ein
Stream ist ganz allgemein eine Abfolge von Bytes. Eine Instanz der Klasse File
Stream repräsentiert den Inhalt einer Text- oder Binärdatei. Andere
Stream-Typen existieren z. B. für den Datenversand über ein
Netzwerk (
System.Net.Sockets.Network
Stream), für eine Byte-Folge im Hauptspeicher (
System.IO.Memory
Stream), eine verschlüsselte Byte-Folge (
System.Security.Crypto¬graphy.Crypto
Stream) oder eine komprimierte Byte-Folge (
System.IO.Compression.GZip
Stream). Basisklasse für alle
Stream-Klassen ist
System.IO.
Stream.
System.IO.
Stream definiert für jeden
Stream einfache Operationen wie CanRead, CanWrite, Read(), Write() und Close(). Komfortablere Zugriffsmöglichkeiten (beispielsweise Peek(), ReadLine(), ReadToEnd(), WriteLine()) existieren in Form so genannter Reader- und Writer-Klassen.
StreamReader und
StreamWriter für
Streams mit
ASCII-Zeichen
BinaryReader und BinaryWriter für
Streams mit beliebigen Byte-Folgen
Beispiel 1: Textdatei schreiben
Das erste Beispiel zeigt das Schreiben einer Protokolldatei mithilfe der Klassen File
Stream und
StreamWriter. Bei einer Binärdatei würden Sie analog die Klasse BinaryWriter verwenden.
// Schreiben einer Protokolldatei
public void Textdatei_Schreiben()
{
// Festlegung der Datei
string dateiName = @".\_daten\dateisystem\protokolldatei.txt";
// Datei öffnen
File
Stream fs = new File
Stream(dateiName, FileMode.OpenOrCreate, FileAccess.Write);
//
Stream öffnen
StreamWriter w = new
StreamWriter(fs);
// Anfügen am Ende
w.Base
Stream.Seek(0, SeekOrigin.End);
// Zeilen schreiben
w.WriteLine("Start des Programms: " + DateTime.Now.ToString());
// Zeichen schreiben ohne Umbruch
w.Write("Datenblock: ");
for (int I = 0; I < 26; i++)
w.Write((char)(97 + i));
// Zeilen schreiben
w.WriteLine();
w.WriteLine("Ende des Programms: " + DateTime.Now.ToString());
// Writer und
Stream schließen
w.Close();
fs.Close();
}
Listing 4: Schreiben einer Textdatei [
System.IO.Demo.cs]
Beispiel 2: Textdatei lesen
Das zweite Beispiel zeigt das zeilenweise Lesen einer Protokolldatei mithilfe der Klassen File¬
Stream und
StreamReader. Bei einer Binärdatei würden Sie analog die Klasse BinaryReader verwenden.
// Lesen aus einer Protokolldatei
public void Textdatei_Lesen()
{
// Festlegung der Datei
string dateiName = @".\_daten\dateisystem\protokolldatei.txt";
// Datei öffnen
File
Stream fs = new File
Stream(dateiName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//
Stream öffnen
StreamReader r = new
StreamReader(fs);
// Zeiger auf den Anfang
r.Base
Stream.Seek(0, SeekOrigin.Begin);
// Alle Zeilen lesen und zeilenweise ausgeben
while (r.Peek() > -1)
Demo.Print(r.ReadLine());
// Reader und
Stream schließen
r.Close();
fs.Close();
}
Listing 5: Auslesen einer Textdatei [
System.IO.Demo.cs]
Übertragen von Daten zwischen Streams
Jeder, der schon einmal mit
Streams gearbeitet hat, kennt Routinen, welche blockweise aus einem
Stream lesen und diese Blöcke in einen anderen
Stream schreiben. Für solche Fälle besitzt die Klasse
Stream ab
.NET 4.0 eine
Methode CopyTo(), welche den
Stream, an welchen die Daten gesendet werden sollen, entgegennimmt. Eine Überladung dieser
Methode nimmt zusätzlich eine Blockgröße in Byte entgegen. Diese gibt an, wie groß die zu übertragenden Blöcke sein sollen. Der Standardwert wurde hierfür auf 4096 festgelegt. Listing 9.17 zeigt ein Beispiel für den Einsatz dieser
Methode. Dieses kopiert die aus dem
Stream input gelesenen Daten in den
Stream output.
public static void Copy
StreamSample()
{
File
Stream input;
File
Stream output;
using (input = new File
Stream(@”c:\temp\a.txt”, FileMode.Open))
{
using (output = new File
Stream(@”c:\temp\b.txt”, FileMode.CreateNew))
{
input.CopyTo(output);
}
}
}
Listing 6: Daten zwischen
Streams übertragen