Skip to content

6. Текстові файли

Текстовий файл — це файл, що містить рядки тексту. Розглянемо створення та використання таких файлів на прикладах.

6.1. Створення та використання

Програма
Результати
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.

Коментарі

  • у рядку 7 створюється об’єкт файлу типу «Scripting.FileSystemObject» за допомогою функції CreateObject(«Scripting.FileSystemObject»). Такий об’єкт дозволяє отримати доступ до будь-якого файлу в системі, а не лише до текстових файлів.
  • У рядку 9 створюється об’єкт «TextStream». Створення цього об’єкта пов’язане зі створенням файлу testfile.txt. Цей файл позначається не абсолютним іменем на кшталт c:\dir1\dir2\....\testfile.txt, а відносним іменем testfile.txt. Отже, він буде створений у каталозі, з якого буде запущено команду на виконання файлу.
  • Файлова система Windows не розрізняє таких понять, як «текстовий файл» чи «нетекстовий файл». Вона розпізнає лише файли. Тому саме програма, яка використовує цей файл, повинна вирішити, чи обробляти його як текстовий файл, чи ні.
  • У рядку 9 створюється об’єкт, з якого походить команда set, що використовується для присвоєння. Створення об’єкта текстового файлу передбачає створення двох об’єктів:
    • створення об’єкта Scripting.FileSystemObject (рядок 7)
    • а потім — створення об’єкта «TextStream» (текстовий файл) за допомогою методу OpenTextFile об’єкта Scripting.FileSystemObject, який приймає кілька параметрів:
      • ім’я файлу, що обробляється (обов’язкове)
      • режим використання файлу. Це ціле число з 3 можливими значеннями:
        • 1: використання файлу для читання
        • 2: використання файлу для запису. Якщо файл ще не існує, а третій параметр присутній і має значення true, файл створюється; інакше — ні. Якщо файл уже існує, його перезаписують.
        • 8: використання файлу в режимі додавання, c.a.d. запис у кінець файлу. Якщо файл ще не існує, а третій параметр присутній і має значення true, файл створюється; інакше — ні.
  • У рядку 11 записується рядок тексту за допомогою методу WriteLine створеного об’єкта TextStream.
  • У рядку 13 файл «закривається». Після цього в нього більше не можна ні записувати, ні читати.
  • У рядку 16 створюється новий об’єкт «TextStream» для роботи з тим самим файлом, що й раніше, але цього разу в режимі «додавання». Нові рядки будуть записані після існуючих.
  • У рядку 18 записуються два нових рядки, враховуючи, що константа vbCRLF є позначкою кінця рядка у текстових файлах.
  • У рядку 20 файл знову закривається
  • у рядку 23 файл знову відкривається в режимі «читання»: ми будемо читати вміст файлу.
  • У рядку 27 зчитується рядок тексту за допомогою методу ReadLine об’єкта TextStream. Коли файл щойно «відкрито», курсор розташовується на першому рядку тексту цього файлу. Після того, як цей рядок прочитано методом ReadLine, курсор переміщується на другий рядок. Таким чином, метод Readline не тільки зчитує поточний рядок, але й автоматично «переходить» до наступного рядка.
  • Щоб обробити всі рядки тексту, метод ReadLine потрібно застосовувати повторно в циклі. Цей цикл (рядок 26) завершується, коли атрибут AtEndOfStream об’єкта TextStream набуває значення true. Це означає, що у файлі більше немає рядків для зчитування.

6.2. Випадки помилок

Існують два типові випадки помилок:

  • відкриття для читання файлу, який не існує
  • відкриття для запису або додавання файлу, якого не існує, при цьому третій параметр у виклику методу OpenTextFile має значення «false».

Наступна програма демонструє, як виявити ці помилки:

Програма
' створення та заповнення текстового файлу
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' створення об’єкта файлу
Set objFichier=CreateObject("Scripting.FileSystemObject")

' відкриття текстового файлу, який повинен існувати, у режимі читання
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    ' файл не існує
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' закриття текстового файлу  
    MyFile.Close
End If


' відкривається текстовий файл, який повинен існувати, у режимі запису
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
    ' закривається текстовий файл
    MyFile.Close
End If

' відкривається текстовий файл, який повинен існувати в режимі додавання
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
    ' закриття текстового файлу
    MyFile.Close
End If

' кінець
wscript.quit 0
Результати
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. Додаток IMPOTS із текстовим файлом

Повернемося до програми розрахунку податку, припустивши, що дані, необхідні для розрахунку податку, містяться у текстовому файлі з назвою 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

Ці три рядки містять, відповідно, дані з таблиць граничних значень coeffR та coeffN програми. Завдяки модульній структурі нашої програми зміни в основному стосуються процедури getData, яка відповідає за формування цих трьох таблиць. Нова програма має такий вигляд:

Програма
' розрахунок податку платника податків
' програму слід запускати з трьома параметрами: одружений, діти, заробітна плата
' одружений: символ O, якщо одружений, N, якщо неодружений
' діти: кількість дітей
' зарплата: річна зарплата без копійок

' обов’язкове оголошення змінних
Option Explicit
Dim erreur

' аргументи отримуються з перевіркою їхньої правильності
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' помилка?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' отримуємо дані, необхідні для розрахунку податку
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' помилка?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' виводиться результат
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' програма завершується без помилок
wscript.quit 0

' ------------ функції та процедури

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' повинен отримати три значення, передані як аргументи до головної програми
    ' аргумент передається програмі без пробілів перед і після нього
    ' для перевірки правильності даних будуть використовуватися регулярні вирази

    ' повертає масив помилок із 2 значеннями
    ' помилка(0): код помилки, 0, якщо помилки немає
    ' помилка(1): повідомлення про помилку, якщо помилка є; інакше — порожній рядок

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

    ' перевіряється наявність 3 аргументів
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' повідомлення про помилку
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' кінець
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' сімейний стан повинен міститися серед символів oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' повідомлення про помилку
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' вихід
        Exit Function
    End If
    ' отримано значення
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' «діти» має бути цілим числом >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' помилка
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' вихід
        Exit Function
    End If
    ' отримуємо значення
    enfants=cint(wscript.arguments(1))

    ' зарплата має бути цілим числом >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' помилка
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' вихід
        Exit Function
    End If
    ' отримуємо значення
    salaire=clng(wscript.arguments(2))

    ' завершено без помилок
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    ' дані трьох таблиць меж, coeffR, coeffN, знаходяться у текстовому файлі
    ' під назвою data.txt. Кожна таблиця займає один рядок у вигляді val1 val2 ... valn
    ' у порядку знаходяться межі: coeffR, coeffN

    ' повертає варіант масиву з 2 елементами для обробки можливої помилки
    ' помилка(0): 0, якщо помилки немає, інакше — ціле число > 0
    ' помилка(1): повідомлення про помилку, якщо помилка

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

    ' створюється об’єкт файлу
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' файл data.txt відкривається для читання
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' помилка?
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' сталася помилка — її фіксують
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' вводимо
        Exit Function
    End If

    ' тепер припускаємо, що вміст правильний, і не проводимо жодної перевірки
    ' зчитуємо 3 рядки

    ' межі
    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

    ' файл закрито
    MyFile.close

    ' завершено без помилок
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' вносить у масив числові значення, що містяться в рядку
    ' вони розділені одним або кількома пробілами

    ' спочатку масив порожній
    tableau=array()
    ' визначається шаблон для рядка
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

    ' проводиться аналіз рядка
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' змінюємо розмір масиву
        ReDim Preserve tableau(i)
        ' присвоюється значення новому елементу
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'кінець
End Sub




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

    ' обчислюється кількість часток
    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

    ' розраховується сімейний коефіцієнт та оподатковуваний дохід
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' розраховується податок
    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

Коментарі:

  • у текстовому файлі data.txt значення можуть бути розділені одним або кількома пробілами, тому неможливо використати функцію split для вилучення значень із рядка. Довелося скористатися регулярним виразом
  • функція getData, окрім трьох масивів меж (coeffR, coeffN), повертає результат, що вказує, чи сталася помилка. Цей результат є масивом, що складається з двох елементів. Перший елемент — це код помилки (0, якщо помилки немає), другий — повідомлення про помилку, якщо вона сталася.
  • Функція getData не перевіряє правильність значень, знайдених у файлі data.txt. У реальних умовах вона повинна це робити.