Skip to content

6. Textdateien

Eine Textdatei ist eine Datei, die Textzeilen enthält. Betrachten wir die Erstellung und Verwendung solcher Dateien anhand von Beispielen.

6.1. Erstellung und Verwendung

Programm
Ergebnisse
C:\>cscript fic1.vbs

C:\>dir

FIC1     VBS           352  07/01/02   7:07 fic1.vbs
TESTFILE TXT            25  07/01/02   7:07 testfile.txt

C:\>more testfile.txt

Ceci est un autre test.

Kommentare

  • In Zeile 7 wird mit der Funktion CreateObject("Scripting.FileSystemObject") ein Dateiobjekt vom Typ „Scripting.FileSystemObject“ erstellt. Ein solches Objekt ermöglicht den Zugriff auf alle Dateien im System, nicht nur auf Textdateien.
  • In Zeile 9 wird ein Objekt „TextStream“ erstellt. Die Erstellung dieses Objekts ist mit der Erstellung der Datei testfile.txt verbunden. Diese Datei wird nicht durch einen absoluten Pfadnamen wie c:\dir1\dir2\....\testfile.txt bezeichnet, sondern durch einen relativen Pfadnamen testfile.txt. Sie wird dann in dem Verzeichnis erstellt, von dem aus der Befehl zur Ausführung der Datei gestartet wird.
  • Das Dateisystem von Windows kennt keine Konzepte wie Textdatei oder Nicht-Textdatei. Es kennt nur Dateien. Es ist daher Aufgabe des Programms, das diese Datei verarbeitet, zu entscheiden, ob es sie als Textdatei behandelt oder nicht.
  • In Zeile 9 wird ein Objekt erstellt, aus dem der Befehl set für die Zuweisung stammt. Die Erstellung eines Textdateiobjekts erfolgt über die Erstellung von zwei Objekten:
    • die Erstellung eines Objekts Scripting.FileSystemObject (Zeile 7)
    • und anschließend die Erstellung eines Objekts „TextStream“ (Textdatei) über die Methode OpenTextFile des Objekts Scripting.FileSystemObject, die mehrere Parameter akzeptiert:
      • den Namen der zu bearbeitenden Datei (obligatorisch)
      • den Verwendungsmodus der Datei. Dabei handelt es sich um eine Ganzzahl mit drei möglichen Werten:
        • 1: Datei im Lesemodus verwenden
        • 2: Die Datei wird zum Schreiben verwendet. Wenn sie noch nicht existiert und der dritte Parameter vorhanden ist und den Wert „true“ hat, wird sie angelegt, andernfalls nicht. Wenn sie bereits existiert, wird sie überschrieben.
        • 8: Datei im Anfüge-Modus verwenden, c.a.d. Schreiben am Ende der Datei. Wenn die Datei noch nicht existiert und der dritte Parameter vorhanden ist und den Wert „true“ hat, wird sie angelegt, andernfalls nicht.
  • Zeile 11 schreibt eine Textzeile mit der Methode „WriteLine“ des erstellten Objekts „TextStream“.
  • Zeile 13 „schließt“ die Datei. Es kann dann nicht mehr in sie geschrieben oder aus ihr gelesen werden.
  • In Zeile 16 wird ein neues Objekt „TextStream“ erstellt, um dieselbe Datei wie zuvor zu bearbeiten, diesmal jedoch im Modus „Hinzufügen“. Die neuen Zeilen werden hinter den bestehenden Zeilen geschrieben.
  • Zeile 18 schreibt zwei neue Zeilen, wobei die Konstante vbCRLF das Zeilenendezeichen für Textdateien darstellt.
  • Zeile 20 schließt die Datei wieder.
  • Zeile 23 öffnet sie erneut im Modus „Lesen“: Der Inhalt der Datei wird gelesen.
  • Zeile 27 liest eine Textzeile mit der Methode ReadLine des Objekts TextStream. Wenn die Datei gerade „geöffnet“ wurde, befindet sich der Cursor auf der ersten Textzeile der Datei. Nachdem diese mit der Methode ReadLine gelesen wurde, befindet sich der Cursor auf der zweiten Zeile. Somit liest die Methode Readline nicht nur die aktuelle Zeile, sondern „springt“ anschließend automatisch zur nächsten Zeile.
  • Um alle Textzeilen zu verarbeiten, muss die Methode ReadLine in einer Schleife wiederholt angewendet werden. Diese Schleife (Zeile 26) endet, wenn das Attribut AtEndOfStream des Objekts TextStream den Wert true annimmt. Dies bedeutet dann, dass keine Zeilen mehr aus der Datei gelesen werden können.

6.2. Fehlerfälle

Es treten zwei häufige Fehlerfälle auf:

  • Öffnen einer nicht vorhandenen Datei zum Lesen
  • das Öffnen zum Schreiben oder das Hinzufügen einer nicht vorhandenen Datei, wobei der dritte Parameter beim Aufruf der Methode OpenTextFile auf „false“ gesetzt ist.

Das folgende Programm zeigt, wie diese Fehler erkannt werden können:

Programm

' Erstellung und Ausfüllen einer Textdatei
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' Es wird ein Dateiobjekt angelegt
Set objFichier=CreateObject("Scripting.FileSystemObject")

' Eine bereits vorhandene Textdatei wird im Lesemodus geöffnet
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then
     ' Die Datei existiert nicht
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
     ' Die Textdatei wird geschlossen
    MyFile.Close
End If


' Eine bereits vorhandene Textdatei wird zum Schreiben geöffnet
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForWriting, False)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
     ' Die Textdatei wird geschlossen
    MyFile.Close
End If

' Eine Textdatei wird im Modus „Hinzufügen“ geöffnet, die bereits vorhanden sein muss
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForAppending, False)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
     ' Die Textdatei wird geschlossen
    MyFile.Close
End If

' Ende
wscript.quit 0

Ergebnisse

C:\>dir

FIC1     VBS           964  07/01/02   7:54 fic1.vbs
TESTFILE TXT             0  07/01/02   8:18 testfile.txt
FIC2     VBS         1 252  07/01/02   8:23 fic2.vbs
3 fichier(s)              2 216 octets
2 répertoire(s)        4 007.11 Mo libre

C:\>cscript fic2.vbs

Le fichier [abcd] n'existe pas
Le fichier [abcd] n'existe pas
Le fichier [abcd] n'existe pas

6.3. Die Anwendung IMPOTS mit einer Textdatei

Wir greifen die Anwendung zur Steuerberechnung wieder auf und gehen davon aus, dass sich die für die Steuerberechnung erforderlichen Daten in einer Textdatei namens data.txt befinden:

12620 13190 15640 24740 31810 39970 48360 55790 92970 127860 151250 172040 195000 0
0 0,05 0,1 0,15 0,2 0,25 0,3 0,35 0,4 0,45 0,5 0,55 0,6 0,65
0 631 1290,5 2072,5 3309,5 4900 6898,5 9316,5 12106 16754,5 23147,5 30710 39312 49062

Die drei Zeilen enthalten jeweils die Daten der Grenztabellen coeffR und coeffN der Anwendung. Dank der Modularisierung unserer Anwendung erfolgen die Änderungen im Wesentlichen in der Prozedur getData, die für die Erstellung der drei Tabellen zuständig ist. Das neue Programm lautet wie folgt:

Programm

' Berechnung der Steuer eines Steuerpflichtigen
' Das Programm muss mit drei Parametern aufgerufen werden: verheiratet, Kinder, Gehalt
' verheiratet: Zeichen O, wenn verheiratet, N, wenn unverheiratet
' Kinder: Anzahl der Kinder
' Gehalt: Jahresgehalt ohne Cent

' obligatorische Variablendeklaration
Option Explicit
Dim erreur

' Die Argumente werden abgerufen und auf ihre Gültigkeit überprüft
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' Fehler?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' Die für die Steuerberechnung erforderlichen Daten werden abgerufen
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' Fehler?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' Das Ergebnis wird angezeigt
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' Beenden ohne Fehler
wscript.quit 0

' ------------ Funktionen und Prozeduren

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
     ' muss drei Werte abrufen, die als Argumente an das Hauptprogramm übergeben wurden
     ' Ein Argument wird ohne Leerzeichen davor und dahinter an das Programm übergeben
     ' Zur Überprüfung der Gültigkeit der Daten werden reguläre Ausdrücke verwendet

     ' gibt eine Fehler-Array-Variant mit zwei Werten zurück
     ' Fehler(0): Fehlercode, 0, wenn kein Fehler vorliegt
     ' Fehler(1): Fehlermeldung, falls ein Fehler vorliegt, andernfalls eine leere Zeichenkette

    Dim syntaxe
    syntaxe= _
    "Syntaxe : pg marié enfants salaire" & vbCRLF & _
    "marié : caractère O si marié, N si non marié" & vbCRLF & _
    "enfants : nombre d'enfants (entier >=0)" & vbCRLF & _
    "salaire : salaire annuel sans les centimes (entier >=0)"

     ' Es wird überprüft, ob 3 Argumente vorhanden sind
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
         ' Fehlermeldung
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
         ' Ende
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

     ' Der Familienstand muss aus den Zeichen oOnN bestehen
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
         ' Fehlermeldung
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
         ' Beenden
        Exit Function
    End If
     ' Wert abrufen
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

     ' „Kinder“ muss eine ganze Zahl >= 0 sein
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
         ' Fehler
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
         ' Beenden
        Exit Function
    End If
     ' Wert wird abgerufen
    enfants=cint(wscript.arguments(1))

     ' Das Gehalt muss eine ganze Zahl >= 0 sein
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
         ' Fehler
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
         ' Beenden
        Exit Function
    End If
     ' Wert wird abgerufen
    salaire=clng(wscript.arguments(2))

     ' Der Vorgang wurde ohne Fehler abgeschlossen
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
     ' Die Daten der drei Grenzwerttabellen coeffR und coeffN befinden sich in einer Textdatei
     ' mit dem Namen data.txt. Jedes Array nimmt eine Zeile in der Form val1 val2 ... valn ein
     ' finden sich in der Reihenfolge die Grenzwerte coeffR und coeffN

     ' gibt eine Fehlervariante mit zwei Elementen zurück, um einen möglichen Fehler zu behandeln
     ' Fehler(0): 0, wenn kein Fehler vorliegt, andernfalls eine ganze Zahl > 0
    ' Fehler(1): die Fehlermeldung, falls ein Fehler vorliegt

    Dim objFichier,MyFile,codeErreur
    Const ForReading = 1, dataFileName="data.txt"

     ' Es wird ein Dateiobjekt erstellt
    Set objFichier=CreateObject("Scripting.FileSystemObject")
     ' Die Datei data.txt wird zum Lesen geöffnet
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
     ' Fehler?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
         ' Es ist ein Fehler aufgetreten – wird vermerkt
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
         ' Eingabe
        Exit Function
    End If

     ' Es wird nun davon ausgegangen, dass der Inhalt korrekt ist, und es wird keine Überprüfung durchgeführt
     ' Die drei Zeilen werden gelesen

     ' Grenzwerte
    Dim ligne, i
    ligne=MyFile.ReadLine
    getDataFromLine ligne,limites

     ' coeffR
    ligne=MyFile.ReadLine
    getDataFromLine ligne,coeffR


     ' coeffN
    ligne=MyFile.ReadLine
    coeffN=split(ligne," ")
    getDataFromLine ligne,coeffN

     ' Die Datei wird geschlossen
    MyFile.close

     ' Fertig, ohne Fehler
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
     ' Die in der Zeile enthaltenen numerischen Werte werden in eine Tabelle übertragen
     ' Diese sind durch ein oder mehrere Leerzeichen getrennt

     ' Zu Beginn ist das Array leer
    tableau=array()
     ' Es wird ein Muster für die Zeile definiert
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

     ' die Zeile wird analysiert
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
         ' Das Array wird in der Größe angepasst
        ReDim Preserve tableau(i)
         ' dem neuen Element wird ein Wert zugewiesen
        tableau(i)=cdbl(correspondances(i).value)
    Next

     'Ende
End Sub




' ----------- calculerImpot
Function calculerImpot(byval marie,ByVal enfants,ByVal salaire, ByRef limites, ByRef coeffR, ByRef coeffN)

     ' Die Anzahl der Anteile wird berechnet
    Dim nbParts
    If marie=true Then
        nbParts=(enfants/2)+2
    Else
        nbParts=(enfants/2)+1
    End If
    If enfants>=3 Then nbParts=nbParts+0.5

     ' Der Familienquotient und das zu versteuernde Einkommen werden berechnet
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

     ' die Steuer wird berechnet
    Dim i, impot
    i=0
    Do While i<ubound(limites) And qf>limites(i)
        i=i+1
    Loop
    calculerImpot=int(revenu*coeffr(i)-nbParts*coeffn(i))
End Function

Anmerkungen:

  • In der Textdatei data.txt können die Werte durch ein oder mehrere Leerzeichen getrennt sein, weshalb die Funktion „split“ nicht verwendet werden kann, um die Werte der Zeile zu extrahieren. Daher musste ein regulärer Ausdruck verwendet werden
  • Die Funktion getData liefert neben den drei Grenzwert-Arrays coeffR und coeffN ein Ergebnis, das angibt, ob ein Fehler aufgetreten ist oder nicht. Dieses Ergebnis ist ein Array-Variant mit zwei Elementen. Das erste Element ist ein Fehlercode (0, wenn kein Fehler vorliegt), das zweite die Fehlermeldung, falls ein Fehler aufgetreten ist.
  • Die Funktion getData prüft nicht die Gültigkeit der in der Datei data.txt gefundenen Werte. In der Praxis sollte sie dies jedoch tun.