Galileo Computing < openbook >
Galileo Computing - Bücher zur Programmierung und Softwareentwicklung
Galileo Computing - Bücher zur Programmierung und Softwareentwicklung

...powered by haas.homelinux.net...

Einstieg in VB.NET von René Martin
- Für Programmiereinsteiger -
Einstieg in VB.NET
gp Kapitel 6 Strings und Datumsangaben
  gp 6.1 Verketten von Strings
  gp 6.2 Strings zerlegen
  gp 6.3 String und Format
  gp 6.4 Datumsfunktionen
  gp 6.5 Zusammenfassung


Galileo Computing

6.2 Strings zerlegen  toptop

Der umgekehrte Schritt ist nicht ganz so einfach. Die Funktionen, mit denen Zeichenketten zerlegt werden können, sind nicht trivial.

Angenommen, wir haben eine Variable

Dim strText As String = "Apfelkuchen"

dann liefert

strText.Length

die Anzahl der Zeichen.

Abbildung

Abbildung 6.1   Der Text ist 11 Zeichen lang.

Ein bestimmtes Zeichen erhält man mit der Eigenschaft Chars. Achtung: Die Zählung beginnt bei 0! Um das »A« aus dem Text herauszulösen, wird also folgender Befehl benötigt:

strText.Chars(0)

Um ihn ganz korrekt weiterzuverarbeiten, muss noch die Methode ToString verwendet werden. Sollen mehrere Zeichen herausgelöst werden, dann so:

strText.Substring(2, 5)

Die überladene Methode Substring verlangt entweder nur die Position, ab welcher bis zum Ende herausgelöst werden soll, oder die Angabe, ab welcher Position bis zu welcher Position. Achtung: Die erste Zahl ist der Start-Index. Ab dieser Position wird herausgeschnitten. Jedoch beginnt die Zählung bei 0! Das obige Beispiel liefert deshalb »felku« und nicht »pfelk«.

Abbildung

Abbildung 6.2   strText.Substring(2, 5)

Das Gegenteil bewirkt IndexOf. Damit kann nach einer Zeichenkette gesucht werden. Die Funktion kann in der Form

strText.IndexOf("c")

geschrieben werden oder mit Parametern, die angeben, ab welcher Position und bis zu welcher gesucht werden soll. Achtung: Auch hier beginnt die Zählung wieder bei 0! strText.IndexOf("c") liefert folglich 7. strText.IndexOf("A") ergibt 0 und strText.IndexOf("x") gibt den Wert –1 zurück.

Analog arbeitet LastIndexOf – damit wird die Position des letzten gefundenen Zeichens ermittelt. Beispielsweise ergibt

strText.LastIndexOf("e")

die Zahl 9 (und nicht 3).

Abbildung

Abbildung 6.3   Man kann überprüfen, ob und wo ein Zeichen in einem String vorhanden ist.

Soll überprüft werden, ob eine Zeichenkette mit einem bestimmten Zeichen endet, dann existiert dafür die Methode EndsWith. Sie liefert »True« oder »False«. Im folgenden Fall ist »True« das Ergebnis:

strText.EndsWith("en")
Abbildung

Abbildung 6.4   Die Endung des Textes

Analog arbeitet die Funktion StartsWith. Sollen ein oder mehrere Zeichen ersetzt werden, so funktioniert dies mit der Methode Replace:

strText.Replace("kuchen", "torte")

... und schon gibt es »Apfeltorte«. Übrigens kann der »kuchen« gelöscht werden:

strText.Remove(5, 6)

Die erste Zahl gibt die Position an, ab der gelöscht wird, die zweite die Anzahl der Zeichen, die gelöscht werden sollen.

Stellen Sie sich eine Zeichenkette vor, die durch bestimmte Zeichen getrennt ist, beispielsweise ein Vor- und ein Zuname:

Dim strText As String = "Theodor W. Adorno"

Der Name soll in seine drei Einzelbestandteile zerlegt werden. Dazu wird ein Array benötigt, in welchem die einzelnen Elemente gespeichert werden können:

Dim strTeile() As String

Die umständliche Variante wäre, den Text Zeichen für Zeichen zu durchlaufen, an ein Feld zu übergeben und danach wieder zusammenzusetzen. Auch wenn es zwei einfache Befehle für diese Aufgabe gibt, so soll dennoch die komplizierte Variante auch gezeigt werden, da die Aufgabenstellung nicht immer so klar ist und man sich ab und zu mit komplexerem Code behelfen muss:

Dim intLetzte As Integer = 0
Dim j As Integer = 0

For i = 0 To strText.Length – 1
   If strText.Substring(i, 1) = " " Then
      ReDim Preserve strTeile(j)
      strTeile(j) = _
      strText.Substring(intLetzte, i - intLetzte) _
      j += 1
      intLetzte = i + 1
   End If
Next

Eine Schleife läuft über alle Zeichen des eingegeben Texts und überprüft, ob es sich um ein Leerzeichen handelt. Falls ja (strText.Substring(i, 1) = " "), so wird das Datenfeld neu dimensioniert, wobei die schon vorhandenen Werte nicht gelöscht werden dürfen. Nun wird an das neue Datenfeld von der zuletzt gefundenen Position (intPosition) bis zur aktuellen alles an dieses neue Feld übergeben (strText.Substring(intLetzte, i - intLetzte)). Danach muss das Programm sich die aktuelle Position als letzte »merken«. Danach (oder schon davor) kann man über verschiedene Möglichkeiten prüfen, ob in dem Text überhaupt ein Leerzeichen war:

If j = 0 Then
   MessageBox.Show _
   ("Es existiert kein Leerzeichen in """ & _
   strText & """.")
   Exit Sub

Falls doch, so wird auch noch der letzte Teil übergeben:

Else
   ReDim Preserve strTeile(j)
   strTeile(j) = strText.Substring(intLetzte)
End If
strText = ""

Das letzte Datenfeld erhält den »Rest«: strTeile(j) =
strText.Substring(intLetzte)
.

Mit einer Schleife können alle Elemente durchlaufen werden. Die Anzahl der Datensätze des Arrays wird über Length ermittelt, da uns ein eindimensionales Datenfeld vorliegt:

Dim i As Integer
For i = 0 To strTeile.Length - 1
   strText = strText & "/" & strTeile(i)
Next
Abbildung

Abbildung 6.5   Das Zerlegen funktioniert.

Abbildung

Abbildung 6.6   Das Überprüfen klappt auch.

Die Funktionen Join und Split leisten das Gleiche. Für unser Beispiel sieht das wie folgt aus:

strTeile = strText.Split(" ")
        strText = strText.Join("/", strTeile)
Abbildung

Abbildung 6.7   Mehrere Leerzeichen hintereinander werden als Trennzeichen wahrgenommen.

Die Methoden Trim, TrimEnd und TrimStart löschen Leerzeichen am Anfang und/oder am Ende der Zeichenkette.

Schließlich halte ich die beiden Funktionen ToLower und ToUpper für wichtig. Mit ihrer Hilfe kann ein Text in Groß- oder Kleinbuchstaben verwandelt werden.

Dies sind alles lustige Funktionen, allerdings stellt sich Frage, wer denn so etwas braucht. Hierzu ein paar Beispiele, die den Gebrauch veranschaulichen.

Die Funktion Trim verwende ich immer, um sicherzustellen, dass der Anwender kein Leerzeichen vor oder nach der Eingabe getippt hat. Es gibt Benutzer, die schreiben Text in eine Combobox (obwohl man ihn auswählen könnte) und beenden die Eingabe mit einem Leerzeichen. Damit steht beispielsweise nicht mehr »München«, sondern »München « im Kombinationsfeld, was als zwei verschiedene Orte interpretiert und verarbeitet wird.

In einem Textfeld stehen Vor- und Zunamen. Sie sollten getrennt werden. Dafür ist die Funktion Split zuständig. Oder etwas eleganter: Zuerst werden die Leerzeichen davor und danach entfernt:

Dim strText As String = Me.txtName.Text
strText = strText.Trim

Dann wird überprüft, ob kein Leerzeichen im Namen vorkommt:

If strText.IndexOf(" ") = -1 Then
   MessageBox.Show("Der Name lautet: " & _
   strText)
Else
...

Bei zwei oder mehr Bestandteilen wird mit Split zerlegt:

strTeile = strText.Split(" ")

Nun werden der zweite bis n-2-te Teil eingesammelt und beschriftet mit: »Der 2. Vorname lautet:«, »Der 3. Vorname lautet:« ... Sollte es nur zwei Bestandteile geben, dann wird die Schleife übergangen – dann läuft sie von 2 bis 1.

Dim strAnzeige As String

strText = Me.txtName.Text
strTeile = strText.Split(" ")
For i = 1 To strTeile.Length – 2
   strAnzeige = strAnzeige & "Der " & _
   (i + 1).ToString & ". Vorname lautet: " & _
   strTeile(i) & vbCr _
Next

MessageBox.Show("Der Vorname lautet: " & _
strTeile(0) & vbCr & _
strAnzeige & "Der Zuname lautet: " & _
strTeile(strTeile.Length - 1))
Abbildung

Abbildung 6.8   Eine andere Zerlegung

Mit diesen Funktionen kann überprüft werden, ob in einem Eingabefeld für die E–Mail-Adresse ein Punkt und ein »@« eingegeben wurden oder ob im Postleitzahlenfeld nur vier- oder fünfstellige Zahlen stehen. Manche Systeme liefern auch vor und hinter den Daten Anführungsstriche. Diese müssen entfernt werden. Oder, und damit sind wir wieder bei unserem Thema: Beim Zugriff auf Dateien.

Angenommen, zwei Dateinamen werden überprüft, dann kann es vorkommen, dass sie in unterschiedlicher Schreibweise vorliegen – der eine in Großbuchstaben, der andere in Groß-/Kleinschreibung. Deshalb kann man mit den Methoden ToLower und ToUpper die Schreibweise in Groß- oder Kleinbuchstaben drehen. Und damit sind sie vergleichbar.

Bei einem Pfad soll überprüft werden, ob das letzte Zeichen ein »\« ist. Falls nicht, soll einer angehängt werden, damit der Dateiname hinzugefügt werden kann. Also wird überprüft:

If strPfad.EndsWiths("\") = False Then
   strPfad &= "\"
End If
strDateiNameGanz = strPfad & strDateiName

Oder aus einem Dateinamen mit Pfadangabe soll der Dateiname herausgelöst werden:

Dim strTeile() As String
strDateiNameGanz = "C:\Eigene Dateien\Test\WW\Versuch.doc"
strTeile = strDateiNameGanz.Split("\")

Damit kann der Dateiname ermittelt werden:

strTeile(strTeile.Length -1)

Andere Variante: Der Dateiname wird ohne Endung angezeigt. Dazu wird die Position des Punktes ermittelt und bis zu dieser Position abgeschnitten:

strDN = strTeile(Length -1)
strDN = strDN.Substring(0, strDN.IndexOf("."))

Das folgende Beispiel verdeutlicht es. In einer Listbox sollen alle Dateinamen von Dateien aufgelistet werden, die sich in einem Ordner befinden:

Dim i As Integer
Dim objDateien() As System.IO.FileInfo
objDateien = New _
DirectoryInfo("C:\Eigene Dateien").GetFiles()
For i = 0 To objDateien.GetUpperBound(0)
   Me.lstDateien.Items.Add _
   (ObjDateien(i).ToString)
Next

Soll die Endung nicht angezeigt werden, dann ist die Schleife wie oben beschrieben zu modifizieren:

Dim strDN As String
For i = 0 To objDateien.Length -1
   strDN = ObjDateien(i).ToString
   strDN = strDN.Substring(0, _
   strDN.LastIndexOf("."))
   Me.lstDateien.Items.Add(strDN)
Next

Beachten Sie, dass ich mit der Methode LastIndexOf und nicht IndexOf gearbeitet habe. Denn wenn eine Datei einen weiteren Punkt im Dateinamen hätte, so würde ab diesem Punkt der übrige Text abgeschnitten.

Leider stellt die Methode GetFiles keinen Parameter zur Verfügung, mit dem nicht nur das angegebene Verzeichnis durchsucht wird, sondern auch alle Unterverzeichnisse. Deshalb müssen mit einer Schleife alle Unterverzeichnisse durchlaufen und von jedem gefundenen Verzeichnis die Dateien ausgelesen werden. Die Prozedur, die dies leistet, könnte wie folgt aussehen:

Sub DateienAuflisten(ByVal strOrdner As String)
   Dim objDateien() As System.IO.FileInfo
   Dim i As Integer
   Dim strDN As String
   objDateien = New DirectoryInfo(strOrdner). _
      GetFiles()

   For i = 0 To objDateien.GetUpperBound(0)
      strDN = ObjDateien(i).ToString
      strDN = strDN.Substring(0, strDN.IndexOf("."))
      Me.lstDateien.Items.Add(strDN)
   Next
End Sub

Ein Ordner wird in dieser Prozedur vom Typ String übergeben. Aus diesem Ordner werden alle darin befindlichen Dateien ausgelesen und in einem Array gespeichert. Eine Schleife durchläuft diese Liste, streicht die Endungen weg und zeigt sie in der Listbox an. Die Prozedur könnte folgendermaßen aufgerufen werden:

Dim objOrdner() As System.IO.DirectoryInfo
   Dim i As Integer
   objOrdner = New DirectoryInfo("C:\Eigene Dateien"). _
   GetDirectories()

   For i = 0 To objOrdner.Length -1
   DateienAuflisten("C:\Eigene Dateien" & _
   objOrdner.(i).ToString)
Next

Einen kleinen Schönheitsfehler hat diese Prozedur. Der Array objOrdner sammelt alle Verzeichnisse aus C:\Eigene Dateien ein und übergibt sie an die Prozedur DateienAuflisten. Dabei fehlen nun allerdings die Dateien aus C:\Eigene Dateien. Man könnte sie ebenfalls in die Liste aufnehmen lassen, indem man vor oder nach der Schleife den Befehl setzt:

DateienAuflisten("C:\Eigene Dateien")

Und die Unterverzeichnisse? Das wird ein bisschen kompliziert, weil nicht bekannt ist, wie viele Ebenen abgearbeitet werden müssen. Deshalb muss man eine Prozedur schreiben, die sich so lange selbst aufruft, bis alle Unterverzeichnisse ausgelesen sind. Die Prozedur DateienAuflisten bleibt unverändert. Die Prozedur, die sich selbst aufruft, könnte so aussehen:

Private Sub OrdnerSuchen(ByVal objOrdner As _
   System.IO.DirectoryInfo)
   Dim i As Integer
   Dim objOrdnerListe() As System.IO.DirectoryInfo
   DateienAuflisten(objOrdner.FullName)

   objOrdnerListe = objOrdner.GetDirectories
   If objOrdnerListe.GetUpperBound(0) > 0 Then
      For i = 0 To objOrdnerListe.GetUpperBound(0) 
         OrdnerSuchen(objOrdnerListe(i))
      Next
   End If
End Sub

Das Prinzip ist einfach: Es wird überprüft, ob sich weitere Unterordner im aktuellen Ordner befinden. Falls ja, dann wird jeder einzelne genommen und das Programm OrdnerSuchen erneut aufgerufen. Denn diese Prozedur ruft DateienAuflisten auf. Beachten Sie, dass nun mit der Eigenschaft FullName gearbeitet wurde, sonst funktioniert das Programm nicht.

Das Programm OrdnerSuchen könnte wiederum beim Starten der Form so aufgerufen werden:

Dim objOrdner() As System.IO.DirectoryInfo
Dim i As Integer
objOrdner = New DirectoryInfo("C:\Eigene Dateien"). _
   GetDirectories()

DateienAuflisten("C:\Eigene Dateien")
For i = 0 To objOrdner.Lentgh - 1
   OrdnerSuchen(objOrdner(i))
Next
Abbildung

Abbildung 6.9   Die Liste der Dateinamen

Um dem Ganzen noch eines aufzusetzen, soll gleichzeitig der Pfad gespeichert werden. Der Grund? Angenommen, dies ist eine Liste von Dateien, von denen der Benutzer eine auswählt, die anschließend geöffnet wird. Da die Dateien in unterschiedlichen Ordnern liegen, kann nicht einfach ein Ordnername mit dem ausgewählten Text verkettet werden. Mit einem kleinen Trick gelingt es dennoch. Beim Füllen der Liste mit Dateinamen läuft ein Zähler mit, der ein Datenfeld vergrößert. In diesem Datenfeld werden die Pfade, das heißt die vollständigen Dateinamen, gespeichert. Es werden global deklariert:

Dim intDateienZähler As Integer
Dim strPfad() As String

In der Prozedur DateienAuflisten vor oder nach dem Eintragen in die Liste (Add) wird der ganze Dateiname im Array gespeichert:

ReDim Preserve strPfad(intDateienZähler)
strPfad(intDateienZähler) = _
objDateien(i).FullName
intDateienZähler += 1

Beim Laden der Form wurde intDateienZähler auf 0 gesetzt. Und angezeigt wird der Pfad im Label txtDateiName:

Private Sub lstDatei_SelectedIndexChanged(ByVal sender As _
   System.Object, ByVal e As System.EventArgs) Handles _
   lstDatei. SelectedIndexChanged
   Me.txtDateiName.Text = strPfad(Me.lstDatei.SelectedIndex)
End Sub

Dies funktioniert, weil beide Listen bei 0 zu zählen beginnen.

Abbildung

Abbildung 6.10   Die Liste mit komplettem Dateinamen

Die folgende Tabelle listet die wichtigsten String-Funktionen auf:

Tabelle 6.1   Die wichtigsten String-Funktionen
Methode Bedeutung
Length die Anzahl der Zeichen
Compare vergleicht zwei Zeichenketten miteinander
EndsWith endet mit einer Zeichenkette
StartsWith beginnt mit einer Zeichenkette
IndexOf ermittelt die Position eines Zeichens oder einer Zeichenkette in einer anderen
LastIndexOf ermittelt die letzte Position eines Zeichens oder einer Zeichenkette in einer anderen
Insert fügt eine Zeichenkette in eine andere ein
Remove löscht Zeichen in einer Zeichenkette
Replace ersetzt Zeichen in einer Zeichenkette
Substring schneidet ab einer bestimmten Position Zeichen aus einer Zeichenkette heraus
Split zerlegt eine Zeichenkette
Join fügt die Elemente eines Arrays zu einer Zeichenkette zusammen
PadLeft füllt von links mit Leerzeichen auf
PadRight füllt von rechts mit Leerzeichen auf
Trim löscht Leerzeichen vor und nach der Zeichenkette
TrimEnd löscht Leerzeichen nach der Zeichenkette
TrimStart löscht Leerzeichen vor der Zeichenkette
ToLower wandelt in Kleinbuchstaben um
ToUpper wandelt in Großbuchstaben um

  

VB.NET

Einstieg in ASP.NET

Einstieg in C#

Visual C#

VB.NET und Datenbanken

Einstieg in XML