Skip to content

6. Textdateien

Eine Textdatei ist eine Datei, die Textzeilen enthält. Sehen wir uns anhand von Beispielen an, wie solche Dateien erstellt und verwendet werden.

6.1. Erstellung und Verwendung

Programm
Ergebnisse
C:\>cscript fic1.vbs

C:\>dir

FIC1     VBS           352  01.07.02   7:07 fic1.vbs
TESTFILE TXT            25  01.07.02   7:07 testfile.txt

C:\>more testfile.txt

Dies ist ein weiterer Test.

Kommentare

  • In Zeile 7 wird mithilfe der Funktion CreateObject("Scripting.FileSystemObject") ein Dateiobjekt vom Typ „Scripting.FileSystemObject“ erstellt. Ein solches Objekt ermöglicht den Zugriff auf jede Datei im System, nicht nur auf Textdateien.
  • Zeile 9 erstellt ein „TextStream“-Objekt. Die Erstellung dieses Objekts ist mit der Erstellung der Datei testfile.txt verbunden. Diese Datei wird nicht durch einen absoluten Pfad wie c:\dir1\dir2\....\testfile.txt, sondern durch einen relativen Pfad testfile.txt bezeichnet. Sie wird dann in dem Verzeichnis erstellt, aus dem der Befehl zum Ausführen der Datei gestartet wird.
  • Das Windows-Dateisystem kennt keine Konzepte wie Textdateien oder Nicht-Textdateien. Es erkennt lediglich Dateien. Es ist daher Sache des Programms, das diese Datei verwendet, zu entscheiden, ob sie als Textdatei behandelt werden soll oder nicht.
  • In Zeile 9 wird ein Objekt erstellt, daher die Verwendung des SET-Befehls zur Zuweisung. Das Erstellen eines Textdateiobjekts umfasst die Erstellung von zwei Objekten:
    • die Erstellung eines Scripting.FileSystemObject (Zeile 7)
    • gefolgt von der Erstellung eines „TextStream“-Objekts (Textdatei) mithilfe der OpenTextFile-Methode des Scripting.FileSystemObject, die mehrere Parameter akzeptiert:
      • den Namen der zu bearbeitenden Datei (erforderlich)
      • den Dateizugriffsmodus. Dies ist eine Ganzzahl mit drei möglichen Werten:
        • 1: schreibgeschützter Modus
        • 2: Schreibmodus. Wenn die Datei noch nicht existiert und der dritte Parameter vorhanden ist und den Wert „true“ hat, wird sie erstellt; andernfalls nicht. Wenn sie bereits existiert, wird sie überschrieben.
        • 8: Anfüge-Modus, d. h. Schreiben an das Ende der Datei. Wenn die Datei noch nicht existiert und der dritte Parameter vorhanden und auf „true“ gesetzt ist, wird sie erstellt; andernfalls nicht.
  • Zeile 11 schreibt eine Textzeile mithilfe der WriteLine-Methode des erstellten TextStream-Objekts.
  • Zeile 13 „schließt“ die Datei. Sie können nun weder in die Datei schreiben noch aus ihr lesen.
  • Zeile 16 erstellt ein neues „TextStream“-Objekt, um dieselbe Datei wie zuvor zu verwenden, diesmal jedoch im „Anhängen“-Modus. Die Zeilen, die geschrieben werden, werden an die vorhandenen Zeilen angehängt.
  • Zeile 18 schreibt zwei neue Zeilen, wobei zu beachten ist, dass die Konstante vbCRLF die Zeilenende-Markierung für Textdateien ist.
  • Zeile 20 schließt die Datei erneut
  • Zeile 23 öffnet sie erneut im „Lese“-Modus: Wir werden den Inhalt der Datei lesen.
  • Zeile 27 liest eine Textzeile mithilfe der ReadLine-Methode des TextStream-Objekts. Wenn die Datei zum ersten Mal „geöffnet“ wird, steht der Cursor auf der ersten Textzeile. Sobald diese Zeile von der ReadLine-Methode gelesen wurde, springt der Cursor zur zweiten Zeile. Somit liest die ReadLine-Methode nicht nur die aktuelle Zeile, sondern „springt“ auch automatisch zur nächsten Zeile.
  • Um alle Textzeilen zu lesen, muss die ReadLine-Methode in einer Schleife wiederholt angewendet werden. Diese Schleife (Zeile 26) endet, wenn das Attribut AtEndOfStream des TextStream-Objekts auf true gesetzt wird. Das bedeutet, dass in der Datei keine Zeilen mehr zu lesen sind.

6.2. Fehlerfälle

Es gibt zwei häufige Fehlerfälle:

  • Öffnen einer Datei zum Lesen, die nicht existiert
  • Öffnen einer nicht vorhandenen Datei zum Schreiben oder Anhängen, wobei der dritte Parameter beim Aufruf der OpenTextFile-Methode auf „false“ gesetzt ist.

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

Programm

' creating & filling a text file
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' create a file object
Set objFichier=CreateObject("Scripting.FileSystemObject")

' open a text file that should exist in read-only mode
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then
    ' file does not exist
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' close the text file
    MyFile.Close
End If


' open a text file that must be writable
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
    ' close the text file
    MyFile.Close
End If

' open a text file that should exist as an addition
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
    ' close the text file
    MyFile.Close
End If

' end
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 IMPOTS-Anwendung mit einer Textdatei

Wir kehren zur Anwendung zur Steuerberechnung zurück und gehen davon aus, dass sich die zur Steuerberechnung benötigten 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 aus den Arrays „limit“, „coeffR“ und „coeffN“ der Anwendung. Dank des modularen Aufbaus unserer Anwendung werden Änderungen in erster Linie in der Prozedur „getData“ vorgenommen, die für die Erstellung der drei Arrays zuständig ist. Das neue Programm lautet wie folgt:

Programm

' calculating a taxpayer's tax liability
' the program must be called with three parameters: married children salary
' married: character Y if married, N if unmarried
' children: number of children
' salary: annual salary without cents

' mandatory variable declaration
Option Explicit
Dim erreur

' retrieve arguments and check their validity
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' mistake?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' retrieve the data needed to calculate taxes
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' mistake?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' the result is displayed
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' leave without error
wscript.quit 0

' ------------ functions and procedures

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' must retrieve three values passed as arguments to the main program
    ' an argument is passed to the program without spaces in front and behind it
    ' use regular expressions to check data validity

    ' returns an error array variant with 2 values
    ' error(0): error code, 0 if no error
    ' error(1): error message if error otherwise empty string

    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)"

    ' we check that there are 3 arguments
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' error msg
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' end
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' marital status must be among the characters oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' error msg
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' we leave
        Exit Function
    End If
    ' the value
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' children must be an integer >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' error
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' we leave
        Exit Function
    End If
    ' the value
    enfants=cint(wscript.arguments(1))

    ' salary must be an integer >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' error
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' we leave
        Exit Function
    End If
    ' the value
    salaire=clng(wscript.arguments(2))

    ' finished without error
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    ' the data of the three limit tables, coeffR, coeffN are in a text file
    ' called data.txt. Each array occupies a line in the form val1 val2 ... valn
    ' we find, in limit order, coeffR, coeffN

    ' renders a 2-element array error variant to handle possible errors
    ' error(0): 0 if no error, an integer >0 otherwise
    ' error(1): error message if error

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

    ' create a file object
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' open the data.txt file in read mode
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' mistake?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' there has been an error - it is noted
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' we're back
        Exit Function
    End If

    ' we now assume that the content is correct and do no verification
    ' read the 3 lines

    ' limits
    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

    ' close the file
    MyFile.close

    ' finished without error
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' places the numerical values contained in line
    ' these are separated by one or more spaces

    ' initially the table is empty
    tableau=array()
    ' we define a model for the
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140.5 or 140
        .global=true              ' all values
    End With

    ' we analyze the line
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' resize the table
        ReDim Preserve tableau(i)
        ' assign a value to the new element
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'end
End Sub




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

    ' the number of shares is calculated
    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

    ' we calculate the family quotient and taxable income
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' tax calculation
    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

Kommentare:

  • In der Textdatei „data.txt“ können Werte durch ein oder mehrere Leerzeichen getrennt sein, wodurch es unmöglich ist, die Werte mit der Funktion „split“ aus der Zeile zu extrahieren. Es musste ein regulärer Ausdruck verwendet werden
  • Die Funktion „getData“ gibt zusätzlich zu den drei Limit-Arrays „coeffR“ und „coeffN“ ein Ergebnis zurück, das angibt, ob ein Fehler aufgetreten ist oder nicht. Dieses Ergebnis ist ein Variant-Array mit zwei Elementen. Das erste Element ist ein Fehlercode (0, wenn kein Fehler vorliegt), das zweite ist die Fehlermeldung, falls ein Fehler aufgetreten ist.
  • Die Funktion „getData“ überprüft die in der Datei „data.txt“ gefundenen Werte nicht. In einem realen Szenario sollte sie dies tun.