Alles über Dateien 2.2
Vorwort
WICHTIG: Version 2.2: Ich habe die PDF Version in eine BB-Code Version übertragen. Dabei gabs einige kleine Schwierigkeiten, weswegen sich Fehler eingeschlichen haben könnten. Falls ihr welche findet, bitte melden

.
In diesem Artikel werde ich versuchen die wichtigsten Möglichkeiten aufzuzeigen, die das .NET Framework zur Dateimanipulation bietet. Dabei werde ich nicht nur bei einfachen Textdateien bleiben, sondern auch XML Dateien behandeln. Ich verwende die Programmiersprache C# für die Codebeispiele in diesem Artikel. Allerdings sollten sie sich ohne Probleme auch mit anderen .NET Programmiersprachen wie z.B. VB .net umsetzen lassen. Ich werde sowohl auf die klassische Art der Dateimanipulation als auch auf die neuen Möglichkeiten des .NET Frameworks 2.0 eingehen.
Um diesen Artikel zu verstehen und ihn nachvollziehen zu können, sollte das Microsoft .NET Framework 1.x oder 2.0 und eine Entwicklungsumgebung installiert sein. Im empfehle Ihnen entweder die kostenlose Entwicklungsumgebung SharpDevelop einzusetzen, oder die Visual Studio Express Editionen von Microsoft. Außerdem sollten Sie bereits ein wenig Erfahrung mit der Entwicklungsumgebung und der .NET Programmiersprache Ihrer Wahl haben. Den Erklärungen folgt immer ein Codebeispiel, dass das beschriebene Thema an Hand eines Praxisbeispiels vertieft. Die Codebeispiele sind mit vielen Kommentaren ausgestattet.
Ich wünsche Ihnen viel Spaß beim Lesen dieses Artikels. Falls Sie Fragen, Wünsche oder Anregungen haben, bitte diese einfach hier posten

.
Dateien lesen und schreiben
In diesem Kapitel zeige ich Ihnen die Möglichkeiten, Dateien einzulesen und Dinge in Dateien zu schreiben, die das .NET Framework bietet. Die Codebeispiele sind absichtlich einfach gehalten und verzichten auf eine Fehlerbehandlung, welche im Normalfall unbedingt angewendet werden sollte.
Allgemeines
Die Ein und –Ausgabeoperation basieren auf Datenströmen(engl. Streams). Um Daten z.B. von Dateien einzulesen oder Daten in eine Datei zu schreiben, wird zuerst ein Datenstrom erzeugt und dann die Daten geschrieben. Hat man die gewünschten Operationen beendet, sollte man den Dateistrom unbedingt schließen, damit die verwendeten Resourcen freigeben werden. Das Lesen und Schreiben von Daten in Dateien geschieht, wie sie anhand der Erklärungen und der Codebeispiele sehr schnell merken werden, sehr ähnlich.
Zeichensätze
Zum Lesen und Schreiben von Dateien ist es wichtig, welchen Zeichensatz die Datei verwendet. Zeichensätze geben an, welches Zeichen zu welchem Binärcode gehört. Besonders wichtig sind Zeichensätze, wenn man Umlaute oder andere sprachspezifische Zeichen wie z.B. chinesische Zeichen in ein Dokument schreiben will. Verwendet man einen falschen Zeichensatz, erhält man beim Auslesen und Anzeigen einen kryptischen Zeichensalat. Hierzu gibt es ein gutes Codebeispiel von Programmierhans:
Encoding Tester
Dateien schreiben
Daten in Dateien zu schreiben ist mit Hilfe der StreamWriter Klasse keine schwere Aufgabe. Das folgende Beispiel schreibt eine einfache Telefonnummern-Liste in eine Datei mit dem Namen „telefonnummern.txt“, die im Verzeichnis der Anwendung erstellt wird. In einem späteren Codebeispiel werden wir die von diesem Codebeispiel erstellte Datei wieder einlesen und verarbeiten.
Das Schreiben von Dateien geschieht zeilenweise. Zuerst erzeugen wir eine Instanz der Klasse StreamWriter und dann rufen wir für jede Zeile dir wir schreiben möchten die WriteLine() Methode auf und übergibt ihr den Text, den wir in die Zeile schreiben möchten. In unserem Beispiel ist das der Name und die Telefonummer des Kontakts, getrennt mit einem Strichpunkt.
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
StreamWriter writer = File.CreateText(Application.StartupPath +
"\\telefonnummern.txt");
writer.WriteLine("Thomas;223245");
writer.WriteLine("Matze;22741");
writer.WriteLine("Michael;357228");
writer.WriteLine("Richard;242531");
writer.WriteLine("Dominik;242352");
writer.Close();
}
}
}
|
Die neuen Möglichkeiten des .NET Frameworks 2.0
Das .NET Framework bietet in der Version 2.0 eine neue nützliche Funktionen, die zwar nicht notwendig sind, aber die Arbeit mit Dateien wesentlich komfortabler gestalten.
Im wesentlich beziehe ich mich dabei auf die Klasse File, die neue statische Methoden enthält die uns das Schreiben von Dateien erleichtern. Die Methode WriteAllText() schreibt den ihr übergebenen Text in eine Datei. Der Methode WriteAllLines() können Sie ein string Array übergeben, in dem sich die einzelnen Zeilen der Datei befinden.
Das oben gezeige Codebeispiel könnte, mit Hilfe der File Klasse realisiert, auch so aussehen:
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
string[] zeilen = new string[] { "Thomas;223245",
"Matze;22741", "Michael;357228", "Richard;242531", "Dominik;242352" };
File.WriteAllLines(Application.StartupPath +
"\\telefonnummern.txt", zeilen);
}
}
}
|
Dateien lesen
Dateien einzulesen funktioniert fast auf die selbe Weise wie das Schreiben von Dateien. Dazu benutzen wir das Gegenstück der Klasse
StreamWriter: Die Klasse
StreamReader.
Das folgende Beispiel liest die von den obigen Beispielen erzeuge Datei „telefonnummern.txt“ wieder ein und gibt das Ergebnis formatiert über die Konsole aus.
Das Einlesen funktioniert, wie beim Schreiben, zeilenweise. Statt der Methode
WriteLine() rufen wir zum Einlesen die Methode
ReadLine() von
StreamReader auf.
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
StreamReader reader = new StreamReader(Application.StartupPath
+ "\\telefonnummern.txt");
do
{
string[] zeile = reader.ReadLine().Split(';');
string name = zeile[0];
string telefonnummer = zeile[1];
Console.WriteLine("Name: " + name + " Telefonummer: " + telefonnummer);
} while (reader.Peek() != -1);
reader.Close();
Console.ReadLine();
}
}
}
|
Die neuen Möglichkeiten des .NET Frameworks 2.0
Auch für das Lesen von Dateien hält die Klasse File komfortable Möglichkeiten bereit. Die Gegenstücke zu den oben genannten Schreibmethoden sind ReadAllText() und ReadAllLines(). ReadAllText() liest die Datei ein und gibt den Inhalt als string zurück. ReadAllLines() gibt den Inhalt als String Array zurück.
Die von den Schreibbeispielen erstellte Telefonnummen-Liste könnte auch so eingelesen und ausgegeben werden:
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
string[] zeilen = File.ReadAllLines(Application.StartupPath +
"\\telefonnummern.txt");
foreach (string zeile in zeilen)
{
string[] aufgeteilt = zeile.Split(';');
Console.WriteLine("Name: " + aufgeteilt[0] +
"Telefonnummer: " + aufgeteilt[1]);
}
Console.ReadLine();
}
}
}
|
XML Dateien
Was ist XML? – Einführung
XML („Extensible Markup Language„) ist ein Standard zur Erstellung von Maschinen- und menschenlesbaren Dokumente in Form einer Baumstruktur(Quelle: Wikipedia). Das bedeutet, dass XML Dateien sehr gut strukturierte Dateien sind, die leicht von Programmen eingelesen werden können.
XML ist sehr weit verbreitet. XHTML, RSS und das Dateiformat des kommenden Microsoft Office 2007 sind nur einige populäre und auf XML basierende Dateiformate. Ein weiterer Vorteil von XML ist seine Platformunabhänigkeit. XML kann von von Programmen jedes Betriebssystems eingelesen werden.
Falls Sie weitergehende Informationen über XML möchten, können Sie den ausgezeichneten Wikipedia-Artikel lesen. Im Folgenden werde ich nur einen groben Überblick über den Aufbau von XML Dateien bieten.
In XML Dateien können Sie z.B. Programmeinstellungen abspeichern. Dies werden wir in einem späteren Beispiel auch machen.
Der Aufbau einer XML Datei
Wie bereits erwähnt, sind XML Dateien sehr gut strukturiert. XML Dateien bestehen aus einzelnen Elementen. Diese Elemente jeweils aus dem Start-Tag, dem Inhalt und dem End-Tag. Damit Sie sich das besser vorstellen können, hier ein Auszug aus einer XML Datei:
<Benutzername>Robert
</Benutzername>
Der rote Text ist das Start-Tag. Der Text zwischen spitzen Klammern ist der Name des Tags.
Der grüne Text ist das End-Tag. Es ist gleich aufgebaut wie das Start-Tag, der -Zeichen nach der spitzen Klammer. Wichtig ist,
dass der Text zwischen den Spitzen Klammern gleich wie der Name des Tags ist.
Zwischen diesen beiden Teilen ist der Inhalt des Elements, in diesem Fall "Robert".
Beispiel für ein falsches Element:
<Benutzer>Simon
</Benutzerrrrr>
Das ist falsch, da im End-Tag der Text (grün markiert) anders als der Text im Start-Tag (rot markiert) ist.
Richtig wäre zum Beispiel dieses Element, da der Text im Start- und End-Tag gleich ist:
<Benutzer>Simon
</Benutzer>
Oder auch dieses:
<Obst>Apfel
</Obst>
Verschachtelung
XML Elemente können ineinander verschachtelt werden. Zum Beispiel kann
eine Liste mit Benutzernamen so aussehen:
XML-Code: |
<Benutzerliste>
<Benutzer>Robert</Benutzer>
<Benutzer>Simon</Benutzer>
</Benutzerliste>
|
Wichtig ist, dass jedes Element einen Anfang und ein Ende hat. Zur besseren übersicht habe ich nochmals die Start-Tags rot und die End-Tags grün eingefärbt.
Attribute
Attribute gehören ebenfalls noch zum Aufbau eines Elemente, genauer gesagt
gehören Sie zum Start-Tag. Mit Attributen können Sie zusätzliche
Informationen in einem Element unterbringen.
So könnte es in dem Beispiel der Benutzerliste unterschiedliche Benutzer
geben: Standard-Benutzer und Premium-Benutzer. Diese Information könnten
Attribute werden nach dem Namen des Start-Tags untergebracht.
Beispiel:
<Benutzer
typ="
standard">Robert</Benutzer>
Beispiel für einen Premium-Benutzer:
<Benutzer
typ="
premium">Simon</Benutzer>
Der in den Beispielen rot gefärbte Text ist der Name des Attributs, in unserem Fall „typ“. Der grün gefärbte Text ist der Inhalt des Attributs. In unserer Benutzerliste schreiben wir hier entweder „premium“ oder „standard“.
Elemente ohne echtes End-Tag
Im Zusammenhang mit Attributen gibt es noch eine Besonderheit am Aufbau
von Elementen. In dem vorherigen Beispiel haben wir den Benutzernamen in
den Inhalt des Tags geschrieben und den Typ des Benutzers in ein
entsprechendes Attribut. Wir könnten aber auch für beide Informationen
Attribute verwenden. Dies würde dann so ausschauen:
XML-Code: |
<Benutzer name="Robert" typ="standard " />
|
Da in diesem Fall der Inhalt des Tags leer ist, können wir das End-Tag
weglassen, müssen aber vor der schließenden spitzen Klammer des Start-Tags ein "/"-Zeichen setzen. Beispiel:
XML-Code: |
<Benutzer name="Robert" typ="standard" />
|
Das Start-Tag wird in diesem Fall "Empty-Element-Tag" genannt.
In den folgenden Erklärungsbeispielen schreibe ich aber, wie vorher, den
Benutzernamen in den Inhalt des Tags.
Sonstiges
Hier gebe ich Ihnen noch einige wichtige Informationen, die den Aufbau von ganzen XML Dateien betreffen.
Nur ein Wurzel/Stamm Element ist erlaubt
XML Dokumente brauchen immer genau ein Wurzel/Stamm Element. Das
heißt, dass alle anderen Elemente in diesem Element verschachtelt sein
müssen. Um Ihnen das anschaulich zu machen, sehen Sie nun zwei Beispiele für XML Dateien. Das erste Beispiel ist falsch, da es mehrere Wurzelelemente gibt. Im zweiten Beispiele sind aller anderen Elemente in dem Element "Benutzerliste" verschachtelt, welches das einzige Wurzelement ist.
FALSCH: (Kompletter Dateiinhalt)
XML-Code: |
<Benutzer>Simon</Benutzer>
<Benutzer>Thomas</Benutzer>
|
RICHTIG: (Kompletter Dateiinhalt)
XML-Code: |
<Programmbenutzer>
<Benutzer>Simon</Benutzer>
<Benutzer>Thomas</Benutzer>
</Programmbenutzer>
|
XML Deklaration
Am Anfang einer jeden XML Datei, sollte man eine XML Deklaration setzen. Diese enthält Informationen zur XML Version (wobei momentan die Version 1.0 aktuell ist) und zum Zeichensatz der Datei. Diese XML Deklaration sieht z.B. so aus:
XML-Code: |
<?xml version="1.0" encoding="utf-8" ?>
|
Wie Sie sicher erkennen, hat diese vom Aufbau her eine große Ähnlichkeit zu XML Elementen. So erkennt man die Attribute „version“ und „encoding“. Mithilfe des Attributs „version“ gibt man die XML-Version an und im Attribut encoding den Zeichensatz. Wenn Sie XML-Dateien mithilfe des .NET Frameworks erzeugen, wird diese XML Deklaration automatisch erzeugt.
Erzeugen und Einlesen von XML Dateien
Da Sie sich nun einen groben Überblick über XML verschafft haben sollten, widmen wir uns jetzt dem Erzeugen und Einlesen von XML Dateien mithilfe des .NET Frameworks. Ich werde dabei keine Unterscheidung zwischen den .NET Framework Versionen 1.x und 2.0 machen, da sowohl die aktuellste Version von SharpDevelop und auch die Visual Studio Express Editionen auf .NET 2.0 basieren.
Die folgenden Codebeispiele werden eine einfache Konfigurationsdatei erzeugen und einlesen. Für das Beispiel habe ich folgenden Aufbau gewählt. (Diesen können Sie natürlich an ihre Bedürfnisse anpassen)
XML-Code: |
<?xml version="1.0" encoding="utf-8" ?>
<Einstellungen>
<SplashAnzeigen>Ja</SplashAnzeigen>
<Autoupdate>Nein</Autoupdate>
<Programmversion>1.0.2</Programmversion>
</Einstellungen>
|
Was in den Tags gespeichert werden soll, sollte selbsterklärend sein.
Erzeugen von XML Dateien
Zuerst einmal werden wir ein Programm schreiben, dass so eine Konfigurationsdatei erzeugen kann. Die dafür notewendigen Klassen finden sich im Namensraum System.Xml.
Zum Schreiben von XML Dateien verwenden wir die Klasse XmlWriter. Diese verwendet man, indem man die Methode Create() der Klasse aufruft, also:
C#-Code: |
XmlWriter writer = XmlWriter.Create(Application.StartupPath + "\\configuration.xml");
|
Der XmlWriter funktioniert folgendermaßen: Es wird immer zuerst eine Methode WriteStart..... aufgerufen, dann damit gearbeitet und dann die Methode WriteEnd..... aufgerufen.
Konkret heißt das, dass wir zum Beispiel
WriteStartElement() aufrufen, um ein Element zu erzeugen, dann den Inhalt des Elements mit
WriteString() hineinschreiben oder Attribute mit
WriteAttributeString() erzeugen und danach die Methode
WriteEndElement() aufrufen.
Bevor wir Elemente in die Xml-Datei schreiben können, müssen wir die Methode
WriteStartDocument() aufrufen. Die schreibt die im vorherigen Abschnitt XmlDeklaration beschriebenen Informationen in das Dokument.
Nach der Arbeit müssen wir natürlich wieder
WriteEndDocument() aufrufen. Sie sehen, die Arbeit verläuft immer nach dem gleichen Schema.
Das Ganze klingt jetzt vieleicht etwas kompliziert, aber das folgende Codebeispiel sollte für etwas mehr Klarheit sorgen. Es erzeugt die beschriebene XML-Datei mit dem Namen "configuration.xml" im Verzeichnis der Anwendung.
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
using System.Xml;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
XmlWriter writer = XmlWriter.Create(Application.StartupPath + "\\configuration.xml");
writer.WriteStartDocument();
writer.WriteStartElement("Einstellungen");
writer.WriteStartElement("SplashAnzeigen");
writer.WriteString("Ja");
writer.WriteEndElement();
writer.WriteStartElement("Autoupdate");
writer.WriteString("Nein");
writer.WriteEndElement();
writer.WriteStartElement("Programmversion");
writer.WriteString("1.0.2");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
}
}
}
|
Wie Sie sehen, wird zuerst eine Instanz von XmlWriter erzeugt. Nach wird die Methode
WriteStartDocument() aufgerufen, um mit der Arbeit zu beginnen. Nun wird das Wurzelelement erzeugt, dass in unserem Fall „Einstellungen“ heißt.
Jetzt durchlaufen wir für jedes Element die Prozedur von
WriteStartElement(),
WriteString() und
WriteEndElement().
Schließlich wird das am Anfang erzeugte Wurzelelement genauso wie andere Elemente geschlossen und die Arbeit mithilfe von WriteEndDocument() abgeschlossen.
Abschließend wird der Zugriff auf die Datei mittels Aufruf der
Close() Methode geschlossen.
Lesen von XML-Dateien
Das Lesen von XML-Dateien geschieht fast genau gleich wie das Schreiben. Die Instanz der Klasse XmlReader erzeugen wir wieder mit der Methode Create().
Wir können sofort loslegen ohne vorher eine Methode aufzurufen, um die Arbeit zu beginnen.
Zuerst öffnen wir das Wurzel-Element. Nun durchlaufen wir für jeden Element die Prozedur von
ReadStartElement(),
ReadString() und
ReadEndElement(). Das Ergebnis von ReadString() geben wir gleich über Console.WriteLine() aus, damit wir auch sehen, dass es funktioniert.
Abschließend wird das Wurzel-Element geschlossen und der Dateizugriff beendet.
Damit wir die Ausgaben auf der Konsole auch sehen können, rufen wir die Methode Console.ReadLine() auf.
Damit das Beispiel funktioniert, muss natürlich die Datei "configuration.xml" vorhanden sein.
C#-Code: |
using System;
using System.IO;
using System.Windows.Forms;
using System.Xml;
namespace SimonKnight6600.Tutorials
{
public class Program
{
static void Main()
{
XmlReader reader =
XmlReader.Create(Application.StartupPath + "\\configuration.xml");
reader.ReadStartElement("Einstellungen");
reader.ReadStartElement("SplashAnzeigen");
Console.WriteLine("SplashAnzeigen:
"+reader.ReadString());
reader.ReadEndElement();
reader.ReadStartElement("Autoupdate");
Console.WriteLine("Autoupdate: " + reader.ReadString());
reader.ReadEndElement();
reader.ReadStartElement("Programmversion");
Console.WriteLine("Programmversion: " +
reader.ReadString());
reader.ReadEndElement();
reader.ReadEndElement();
reader.Close();
Console.ReadLine();
}
}
}
|
Anhänge
Nachwort
Ich hoffe, dass Ihnen dieser Artikel gefallen hat und Sie nun wissen, wie man mit Dateien umgeht. Meine größte Sorge beim Schreiben dieses Artikels war, dass er für die Zielgruppe zu kompliziert geschrieben ist. Falls Sie also eine Stelle entdecken, die Sie nicht verstehen, oder sich Fehler eingeschlichen haben, schreiben Sie bitte einen Beitrag in diesem Thread

.