Skip to content

6. Os ficheiros de texto

Um ficheiro de texto é um ficheiro que contém linhas de texto. Vamos analisar a criação e a utilização desses ficheiros através de exemplos.

6.1. Criação e utilização

Programa
Resultados
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.

Comentários

  • A linha 7 cria um objeto de ficheiro do tipo «Scripting.FileSystemObject» através da função CreateObject("Scripting.FileSystemObject"). Esse objeto permite o acesso a qualquer ficheiro do sistema, e não apenas a ficheiros de texto.
  • A linha 9 cria um objeto «TextStream». A criação deste objeto está associada à criação do ficheiro testfile.txt. Este ficheiro não é designado por um nome absoluto do tipo c:\dir1\dir2\....\testfile.txt, mas sim por um nome relativo, testfile.txt. Será, portanto, criado no diretório a partir do qual será executado o comando para abrir o ficheiro.
  • O sistema de ficheiros do Windows não reconhece conceitos como «ficheiro de texto» ou «ficheiro não textual». Reconhece apenas ficheiros. Cabe, portanto, ao programa que utiliza esse ficheiro determinar se o vai tratar como um ficheiro de texto ou não.
  • A linha 9 cria um objeto a partir do qual o comando set é utilizado para a atribuição. A criação de um objeto de ficheiro de texto passa pela criação de dois objetos:
    • a criação de um objeto Scripting.FileSystemObject (linha 7)
    • e, em seguida, a criação de um objeto «TextStream» (ficheiro de texto) através do método OpenTextFile do objeto Scripting.FileSystemObject, que aceita vários parâmetros:
      • o nome do ficheiro a tratar (obrigatório)
      • o modo de utilização do ficheiro. Trata-se de um número inteiro com 3 valores possíveis:
        • 1: utilização do ficheiro em modo de leitura
        • 2: utilização do ficheiro em modo de escrita. Se o ficheiro ainda não existir e se o terceiro parâmetro estiver presente e tiver o valor «true», o ficheiro é criado; caso contrário, não é criado. Se já existir, é sobrescrito.
        • 8: utilização do ficheiro em modo de adição, c.a.d. Escrita no final do ficheiro. Se o ficheiro ainda não existir e se o terceiro parâmetro estiver presente e tiver o valor «true», o ficheiro é criado; caso contrário, não é criado.
  • A linha 11 escreve uma linha de texto com o método WriteLine do objeto TextStream criado.
  • A linha 13 «fecha» o ficheiro. A partir daí, já não é possível escrever nem ler nele.
  • A linha 16 cria um novo objeto «TextStream» para utilizar o mesmo ficheiro que anteriormente, mas desta vez no modo «adição». As linhas que forem escritas serão inseridas a seguir às linhas existentes.
  • A linha 18 escreve duas novas linhas, sabendo que a constante vbCRLF é o marcador de fim de linha dos ficheiros de texto.
  • A linha 20 fecha novamente o ficheiro
  • a linha 23 reabre-o no modo «leitura»: vamos ler o conteúdo do ficheiro.
  • A linha 27 lê uma linha de texto com o método ReadLine do objeto TextStream. Quando o ficheiro acaba de ser «aberto», ficamos posicionados na primeira linha de texto do mesmo. Quando esta for lida pelo método ReadLine, ficamos posicionados na segunda linha. Assim, o método Readline não só lê a linha atual, como também «avança» automaticamente para a linha seguinte.
  • Para processar todas as linhas de texto, o método ReadLine deve ser aplicado repetidamente num ciclo. Este ciclo (linha 26) termina quando o atributo AtEndOfStream do objeto TextStream assume o valor true. Isso significa, então, que já não há mais linhas para ler no ficheiro.

6.2. Casos de erro

Existem dois casos de erro frequentes:

  • abertura para leitura de um ficheiro que não existe
  • Abertura para escrita ou adição de um ficheiro que não existe, com o terceiro parâmetro definido como «false» na chamada ao método OpenTextFile.

O programa seguinte mostra como detetar estes erros:

Programa
' criação e preenchimento de um ficheiro de texto
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' cria-se um objeto de ficheiro
Set objFichier=CreateObject("Scripting.FileSystemObject")

' abre-se um ficheiro de texto que já deve existir, em modo de leitura
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    ' o ficheiro não existe
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' fecha-se o ficheiro de texto  
    MyFile.Close
End If


' abre-se um ficheiro de texto que já deve existir, em modo de escrita
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
    ' fecha-se o ficheiro de texto
    MyFile.Close
End If

' abre-se um ficheiro de texto que deve existir em modo de adição
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
    ' fecha-se o ficheiro de texto
    MyFile.Close
End If

' fim
wscript.quit 0
Resultados
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. A aplicação IMPOTS com um ficheiro de texto

Retomamos a aplicação de cálculo do imposto, partindo do princípio de que os dados necessários para o cálculo do imposto se encontram num ficheiro de texto denominado 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

As três linhas contêm, respetivamente, os dados das tabelas de limites coeffR e coeffN da aplicação. Graças à modularização da nossa aplicação, as alterações ocorrem essencialmente no procedimento getData, responsável pela construção das três tabelas. O novo programa é o seguinte:

Programa
' cálculo do imposto de um contribuinte
' o programa deve ser chamado com três parâmetros: casado, filhos, salário
' casado: caractere O se casado, N se solteiro
' filhos: número de filhos
' salário: salário anual sem os cêntimos

' declaração obrigatória das variáveis
Option Explicit
Dim erreur

' recuperam-se os argumentos verificando a sua validade
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' erro?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' recuperam-se os dados necessários para o cálculo do imposto
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' erro?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' exibe-se o resultado
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' sai sem erros
wscript.quit 0

' ------------ funções e procedimentos

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' deve recuperar três valores passados como argumentos ao programa principal
    ' um argumento é transmitido ao programa sem espaços à frente nem atrás
    ' serão utilizadas expressões regulares para verificar a validade dos dados

    ' retorna uma variante de tipo «tabela de erros» com 2 valores
    ' erro(0): código de erro, 0 se não houver erro
    ' erro(1): mensagem de erro, caso haja erro; caso contrário, a cadeia de caracteres fica vazia

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

    ' verifica-se se existem 3 argumentos
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' mensagem de erro
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' fim
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' o estado civil deve estar entre os caracteres oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' mensagem de erro
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' sair
        Exit Function
    End If
    ' recuperar o valor
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' «filhos» deve ser um número inteiro >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' erro
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' sair
        Exit Function
    End If
    ' recuperar o valor
    enfants=cint(wscript.arguments(1))

    ' o salário deve ser um número inteiro >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' erro
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' sair
        Exit Function
    End If
    ' recuperamos o valor
    salaire=clng(wscript.arguments(2))

    ' concluído sem erros
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    ' os dados das três tabelas de limites, coeffR, coeffN, estão num ficheiro de texto
    ' denominado data.txt. Cada tabela ocupa uma linha na forma val1 val2 ... valn
    ' encontram-se, por ordem, os limites coeffR e coeffN

    ' retorna uma variante de erro com uma tabela de 2 elementos para gerir um eventual erro
    ' erro(0): 0 se não houver erro, um número inteiro > 0 caso contrário
    ' erro(1): a mensagem de erro, caso haja erro

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

    ' cria-se um objeto de ficheiro
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' abre-se o ficheiro data.txt em modo de leitura
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' erro?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' ocorreu um erro — regista-se o erro
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' introduz-se
        Exit Function
    End If

    ' partimos agora do princípio de que o conteúdo está correto e não fazemos qualquer verificação
    ' lemos as 3 linhas

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

    ' fecha-se o ficheiro
    MyFile.close

    ' concluído sem erros
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' insere numa tabela os valores numéricos contidos na linha
    ' estas estão separadas por um ou mais espaços

    ' inicialmente, a tabela está vazia
    tableau=array()
    ' define-se um modelo para a linha
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

    ' analisa-se a linha
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' redimensiona-se a tabela
        ReDim Preserve tableau(i)
        ' atribui-se um valor ao novo elemento
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'fim
End Sub




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

    ' calcula-se o número de quotas
    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

    ' calcula-se o quociente familiar e o rendimento tributável
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' calcula-se o imposto
    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

Comentários:

  • no ficheiro de texto data.txt, os valores podem estar separados por um ou mais espaços, o que torna impossível utilizar a função split para recuperar os valores da linha. Foi necessário recorrer a uma expressão regular
  • a função getData devolve, além das três tabelas de limites (coeffR, coeffN), um resultado que indica se ocorreu ou não um erro. Este resultado é uma variante de tabela com dois elementos. O primeiro elemento é um código de erro (0 se não houver erro), o segundo é a mensagem de erro, caso tenha ocorrido um erro.
  • A função getData não verifica a validade dos valores encontrados no ficheiro data.txt. Em condições reais, deveria fazê-lo.