Skip to content

6. I file di testo

Un file di testo è un file contenente righe di testo. Esaminiamo la creazione e l’utilizzo di tali file attraverso alcuni esempi.

6.1. Creazione e utilizzo

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

Commenti

  • la riga 7 crea un oggetto file di tipo "Scripting.FileSystemObject" tramite la funzione CreateObject("Scripting.FileSystemObject"). Tale oggetto consente l'accesso a qualsiasi file del sistema, non solo ai file di testo.
  • La riga 9 crea un oggetto "TextStream". La creazione di questo oggetto è associata alla creazione del file testfile.txt. Questo file non è indicato da un nome assoluto del tipo c:\dir1\dir2\....\testfile.txt, ma da un nome relativo testfile.txt. Verrà quindi creato nella directory da cui verrà lanciato il comando di esecuzione del file.
  • Il sistema di file di Windows non riconosce concetti quali «file di testo» o «file non di testo». Conosce solo i file. Spetta quindi al programma che utilizza questo file decidere se trattarlo come un file di testo o meno.
  • La riga 9 crea un oggetto da cui deriva il comando set utilizzato per l’assegnazione. La creazione di un oggetto file di testo comporta la creazione di 2 oggetti:
    • la creazione di un oggetto Scripting.FileSystemObject (riga 7)
    • e successivamente la creazione di un oggetto «TextStream» (file di testo) tramite il metodo OpenTextFile dell’oggetto Scripting.FileSystemObject, che accetta diversi parametri:
      • il nome del file da gestire (obbligatorio)
      • la modalità di utilizzo del file. Si tratta di un numero intero con 3 possibili valori:
        • 1: utilizzo del file in lettura
        • 2: utilizzo del file in scrittura. Se il file non esiste già e se il terzo parametro è presente e ha valore true, viene creato; altrimenti no. Se esiste già, viene sovrascritto.
        • 8: utilizzo del file in modalità aggiunta, c.a.d. Scrittura alla fine del file. Se il file non esiste già e se il terzo parametro è presente e ha valore true, viene creato; altrimenti no.
  • La riga 11 scrive una riga di testo con il metodo WriteLine dell'oggetto TextStream creato.
  • La riga 13 «chiude» il file. A questo punto non è più possibile né scrivere né leggere al suo interno.
  • La riga 16 crea un nuovo oggetto "TextStream" per gestire lo stesso file di prima, ma questa volta in modalità "aggiunta". Le righe che verranno scritte saranno inserite dopo quelle esistenti.
  • La riga 18 scrive due nuove righe, tenendo presente che la costante vbCRLF indica la fine di riga nei file di testo.
  • La riga 20 chiude nuovamente il file
  • la riga 23 lo riapre in modalità "lettura": si procederà alla lettura del contenuto del file.
  • La riga 27 legge una riga di testo con il metodo ReadLine dell’oggetto TextStream. Quando il file è stato appena “aperto”, ci si trova sulla prima riga di testo dello stesso. Una volta che questa è stata letta dal metodo ReadLine, ci si posiziona sulla seconda riga. Pertanto, il metodo Readline non solo legge la riga corrente, ma “passa” automaticamente alla riga successiva.
  • Per elaborare tutte le righe di testo, il metodo ReadLine deve essere applicato ripetutamente all’interno di un ciclo. Il ciclo (riga 26) termina quando l’attributo AtEndOfStream dell’oggetto TextStream assume il valore true. Ciò significa che non ci sono più righe da leggere nel file.

6.2. I casi di errore

Si verificano due casi di errore frequenti:

  • apertura in lettura di un file che non esiste
  • apertura in scrittura o aggiunta di un file inesistente con il terzo parametro impostato su false nella chiamata al metodo OpenTextFile.

Il programma seguente mostra come rilevare questi errori:

Programma
' creazione e compilazione di un file di testo
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' si crea un oggetto file
Set objFichier=CreateObject("Scripting.FileSystemObject")

' si apre in lettura un file di testo che deve già esistere
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    ' il file non esiste
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' si chiude il file di testo  
    MyFile.Close
End If


' si apre un file di testo che deve già esistere in modalità di scrittura
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
    ' si chiude il file di testo
    MyFile.Close
End If

' si apre un file di testo che deve già esistere in modalità di aggiunta
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
    ' si chiude il file di testo
    MyFile.Close
End If

' fine
wscript.quit 0
Risultati
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. L'applicazione IMPOTS con un file di testo

Riprendiamo l'applicazione per il calcolo delle imposte supponendo che i dati necessari al calcolo siano contenuti in un file di testo denominato data.txt:

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

Le tre righe contengono rispettivamente i dati delle tabelle limite coeffR e coeffN dell’applicazione. Grazie alla modularizzazione della nostra applicazione, le modifiche riguardano essenzialmente la procedura getData incaricata di costruire le tre tabelle. Il nuovo programma è il seguente:

Programma
' calcolo dell'imposta di un contribuente
' il programma deve essere richiamato con tre parametri: coniugato, figli, stipendio
' coniugato: carattere O se coniugato, N se non coniugato
' figli: numero di figli
' stipendio: stipendio annuale senza i centesimi

' dichiarazione obbligatoria delle variabili
Option Explicit
Dim erreur

' si recuperano gli argomenti verificandone la validità
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' errore?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' si recuperano i dati necessari per il calcolo dell'imposta
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' errore?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' si visualizza il risultato
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' uscita senza errori
wscript.quit 0

' ------------ funzioni e procedure

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' deve recuperare tre valori passati come argomenti al programma principale
    ' un argomento viene trasmesso al programma senza spazi né all’inizio né alla fine
    ' si utilizzeranno espressioni regolari per verificare la validità dei dati

    ' restituisce un array di errori con 2 valori
    ' errore(0): codice di errore, 0 se non ci sono errori
    ' errore(1): messaggio di errore in caso di errore, altrimenti stringa vuota

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

    ' si verifica che ci siano 3 argomenti
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' messaggio di errore
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' fine
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' lo stato civile deve essere uno dei caratteri oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' messaggio di errore
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' uscita
        Exit Function
    End If
    ' si recupera il valore
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' il numero di figli deve essere un numero intero >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' errore
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' uscita
        Exit Function
    End If
    ' si recupera il valore
    enfants=cint(wscript.arguments(1))

    ' lo stipendio deve essere un numero intero >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' errore
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' uscita
        Exit Function
    End If
    ' si recupera il valore
    salaire=clng(wscript.arguments(2))

    ' operazione completata senza errori
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    ' i dati delle tre tabelle limite, coeffR, coeffN, sono contenuti in un file di testo
    ' denominato data.txt. Ogni tabella occupa una riga nella forma val1 val2 ... valn
    ' si trovano, nell'ordine, i valori limite coeffR e coeffN

    ' restituisce una variante "errore tabella" a 2 elementi per gestire l'eventuale errore
    ' errore(0): 0 se non c'è errore, un numero intero >0 altrimenti
    ' errore(1): il messaggio di errore in caso di errore

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

    ' si crea un oggetto file
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' si apre il file data.txt in lettura
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' errore?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' si è verificato un errore - lo si annota
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' si inserisce
        Exit Function
    End If

    ' ora si presume che il contenuto sia corretto e non si effettua alcuna verifica
    ' si leggono le 3 righe

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

    ' si chiude il file
    MyFile.close

    ' Operazione completata senza errori
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' inserisce in una tabella i valori numerici contenuti nella riga
    ' questi sono separati da uno o più spazi

    ' inizialmente la tabella è vuota
    tableau=array()
    ' si definisce un modello per la riga
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

    ' si analizza la riga
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' si ridimensiona la tabella
        ReDim Preserve tableau(i)
        ' si assegna un valore al nuovo elemento
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'fine
End Sub




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

    ' si calcola il numero di quote
    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

    ' si calcolano il quoziente familiare e il reddito imponibile
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' si calcola l'imposta
    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

Note:

  • nel file di testo data.txt, i valori possono essere separati da uno o più spazi, il che rende impossibile utilizzare la funzione split per estrarre i valori dalla riga. È stato necessario ricorrere a un'espressione regolare
  • la funzione getData restituisce, oltre ai tre array di limiti (coeffR, coeffN), un risultato che indica se si è verificato o meno un errore. Questo risultato è un array di due elementi. Il primo elemento è un codice di errore (0 se non c’è stato alcun errore), il secondo è il messaggio di errore se si è verificato un errore.
  • La funzione getData non verifica la validità dei valori presenti nel file data.txt. In una situazione reale, dovrebbe farlo.