Skip to content

6. Tekstbestanden

Een tekstbestand is een bestand dat uit tekstregels bestaat. Laten we aan de hand van voorbeelden eens kijken naar het aanmaken en gebruiken van dergelijke bestanden.

6.1. Aanmaken en gebruik

Programma
Resultaten
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.

Opmerkingen

  • Op regel 7 wordt een bestandsobject van het type "Scripting.FileSystemObject" aangemaakt via de functie CreateObject("Scripting.FileSystemObject"). Met een dergelijk object is toegang mogelijk tot elk bestand in het systeem, niet alleen tot tekstbestanden.
  • Op regel 9 wordt een object "TextStream" aangemaakt. Het aanmaken van dit object gaat gepaard met het aanmaken van het bestand testfile.txt. Dit bestand wordt niet aangeduid met een absolute naam zoals c:\dir1\dir2\....\testfile.txt, maar met een relatieve naam: testfile.txt. Het wordt dan aangemaakt in de map van waaruit het commando voor het uitvoeren van het bestand wordt gestart.
  • Het bestandssysteem van Windows kent geen begrippen als tekstbestand of niet-tekstbestand. Het kent alleen bestanden. Het is dus aan het programma dat dit bestand gebruikt om te bepalen of het als een tekstbestand wordt behandeld of niet.
  • Regel 9 maakt een object aan, waaruit de opdracht set wordt gebruikt voor de toewijzing. Het aanmaken van een tekstbestandsobject verloopt via het aanmaken van twee objecten:
    • het aanmaken van een object Scripting.FileSystemObject (regel 7)
    • en vervolgens het aanmaken van een object „TextStream” (tekstbestand) via de methode OpenTextFile van het object Scripting.FileSystemObject, dat meerdere parameters toestaat:
      • de naam van het te verwerken bestand (verplicht)
      • de gebruiksmodus van het bestand. Dit is een geheel getal met 3 mogelijke waarden:
        • 1: het bestand in leesmodus gebruiken
        • 2: het bestand in schrijfmodus gebruiken. Als het nog niet bestaat en de derde parameter is opgegeven en de waarde 'true' heeft, wordt het aangemaakt; anders niet. Als het al bestaat, wordt het overschreven.
        • 8: het bestand in toevoegmodus gebruiken, c.a.d. schrijven aan het einde van het bestand. Als het bestand nog niet bestaat en de derde parameter aanwezig is en de waarde 'true' heeft, wordt het aangemaakt; anders niet.
  • regel 11 schrijft een tekstregel met de methode WriteLine van het aangemaakte object TextStream.
  • regel 13 „sluit” het bestand. Er kan dan niet meer in worden geschreven of gelezen.
  • regel 16 maakt een nieuw object „TextStream” aan om hetzelfde bestand als eerder te bewerken, maar ditmaal in de modus „toevoegen”. De regels die worden geschreven, worden achter de bestaande regels geplaatst.
  • regel 18 schrijft twee nieuwe regels, waarbij de constante vbCRLF het einde-van-regel-teken is in tekstbestanden.
  • regel 20 sluit het bestand weer
  • regel 23 opent het bestand opnieuw in de modus „lezen”: we gaan de inhoud van het bestand lezen.
  • Regel 27 leest een tekstregel met de methode ReadLine van het object TextStream. Wanneer het bestand net is „geopend”, staat de cursor op de eerste tekstregel ervan. Zodra deze regel is gelezen door de methode ReadLine, wordt de cursor op de tweede regel geplaatst. De methode Readline leest dus niet alleen de huidige regel, maar ‘gaat’ daarna automatisch door naar de volgende regel.
  • Om alle tekstregels te verwerken, moet de methode ReadLine herhaaldelijk in een lus worden toegepast. Deze lus (regel 26) eindigt wanneer het attribuut AtEndOfStream van het object TextStream de waarde true heeft. Dit betekent dan dat er geen regels meer in het bestand te lezen zijn.

6.2. Foutgevallen

Er zijn twee veelvoorkomende foutgevallen:

  • een bestand openen om te lezen dat niet bestaat
  • Een bestand openen om te schrijven of een bestand toevoegen dat niet bestaat, terwijl de derde parameter in de aanroep van de methode OpenTextFile op `false` is ingesteld.

Het volgende programma laat zien hoe deze fouten kunnen worden gedetecteerd:

Programma
' een tekstbestand aanmaken en invullen
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' er wordt een bestandsobject aangemaakt
Set objFichier=CreateObject("Scripting.FileSystemObject")

' een tekstbestand openen dat al moet bestaan, in leesmodus
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    ' het bestand bestaat niet
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' het tekstbestand wordt gesloten  
    MyFile.Close
End If


' een tekstbestand wordt geopend dat al moet bestaan, in schrijfmodus
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
    ' het tekstbestand wordt gesloten
    MyFile.Close
End If

' een tekstbestand wordt geopend dat al moet bestaan, in de modus 'toevoegen'
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
    ' het tekstbestand wordt gesloten
    MyFile.Close
End If

' einde
wscript.quit 0
Resultaten
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. De toepassing IMPOTS met een tekstbestand

We gaan verder met de toepassing voor de belastingberekening, ervan uitgaande dat de gegevens die nodig zijn voor de berekening van de belasting zich in een tekstbestand met de naam data.txt bevinden:

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

De drie regels bevatten respectievelijk de gegevens van de grenswaardetabellen coeffR en coeffN van de applicatie. Dankzij de modularisering van onze applicatie vinden de wijzigingen voornamelijk plaats in de procedure getData, die verantwoordelijk is voor het samenstellen van de drie tabellen. Het nieuwe programma ziet er als volgt uit:

Programma
' berekening van de belasting van een belastingplichtige
' het programma moet worden aangeroepen met drie parameters: gehuwd, kinderen, salaris
' getrouwd: letter O indien getrouwd, N indien ongehuwd
' kinderen: aantal kinderen
' salaris: jaarsalaris zonder centimes

' verplichte declaratie van variabelen
Option Explicit
Dim erreur

' de argumenten worden opgehaald en op geldigheid gecontroleerd
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' fout?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' de gegevens die nodig zijn voor de berekening van de belasting worden opgehaald
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' fout?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' het resultaat wordt weergegeven
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' afsluiten zonder fout
wscript.quit 0

' ------------ functies en procedures

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' moet drie waarden ophalen die als argument aan het hoofdprogramma zijn doorgegeven
    ' een argument wordt zonder spaties ervoor en erachter aan het programma doorgegeven
    ' er worden reguliere expressies gebruikt om de geldigheid van de gegevens te controleren

    ' retourneert een foutvariant-array met 2 waarden
    ' fout(0): foutcode, 0 als er geen fout is
    ' fout(1): foutmelding indien er een fout is, anders de lege tekenreeks

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

    ' er wordt gecontroleerd of er 3 argumenten zijn
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' foutmelding
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' einde
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' de burgerlijke staat moet bestaan uit de tekens oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' foutmelding
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' afsluiten
        Exit Function
    End If
    ' waarde ophalen
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' 'kinderen' moet een geheel getal zijn >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' fout
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' afsluiten
        Exit Function
    End If
    ' de waarde wordt opgehaald
    enfants=cint(wscript.arguments(1))

    ' salaris moet een geheel getal zijn >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' fout
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' afsluiten
        Exit Function
    End If
    ' de waarde wordt opgehaald
    salaire=clng(wscript.arguments(2))

    ' het is zonder fouten voltooid
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    ' de gegevens van de drie limiettabellen, coeffR, coeffN, staan in een tekstbestand
    ' met de naam data.txt. Elke tabel neemt één regel in beslag in de vorm val1 val2 ... valn
    ' vinden we in deze volgorde de limieten: coeffR, coeffN

    ' levert een fouttabel met 2 elementen op om eventuele fouten af te handelen
    ' fout(0): 0 als er geen fout is, anders een geheel getal > 0
    ' fout(1): het foutbericht indien er een fout is

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

    ' er wordt een bestandsobject aangemaakt
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' het bestand data.txt wordt geopend in leesmodus
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' fout?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' er is een fout opgetreden – deze wordt genoteerd
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' we voeren de gegevens in
        Exit Function
    End If

    ' we gaan er nu vanuit dat de inhoud correct is en voeren geen controle uit
    ' we lezen de 3 regels

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

    ' het bestand wordt gesloten
    MyFile.close

    ' het is zonder fouten voltooid
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' zet de numerieke waarden uit de rij in een tabel
    ' deze worden gescheiden door een of meer spaties

    ' in het begin is de tabel leeg
    tableau=array()
    ' hier wordt een sjabloon voor de regel gedefinieerd
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

    ' de regel wordt geanalyseerd
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' de afmetingen van de tabel worden aangepast
        ReDim Preserve tableau(i)
        ' er wordt een waarde toegewezen aan het nieuwe element
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'einde
End Sub




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

    ' het aantal aandelen wordt berekend
    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

    ' het gezinsquotiënt en het belastbaar inkomen worden berekend
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' de belasting wordt berekend
    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

Opmerkingen:

  • in het tekstbestand data.txt kunnen de waarden door één of meerdere spaties worden gescheiden, waardoor het onmogelijk is om de functie split te gebruiken om de waarden uit de regel te halen. Er moest een reguliere expressie worden gebruikt
  • De functie getData levert, naast de drie limiettabellen coeffR en coeffN, een resultaat op dat aangeeft of er al dan niet een fout is opgetreden. Dit resultaat is een variant-tabel met twee elementen. Het eerste element is een foutcode (0 als er geen fout is), het tweede element is de foutmelding als er een fout is opgetreden.
  • De functie getData controleert niet of de waarden in het bestand data.txt geldig zijn. In de praktijk zou dit wel moeten gebeuren.