4. Поширені класи .NET
Тут ми представимо кілька класів платформи .NET, які можуть бути цікавими навіть для початківців. Спочатку ми покажемо, як отримати інформацію про сотні доступних класів.
4.1. Пошук допомоги з SDK.NET
4.1.1. wincv
Якщо встановлено лише SDK, а не Visual Studio.NET, можна скористатися програмою wincv.exe, яка зазвичай знаходиться в каталозі SDK, наприклад, C:\Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1. При запуску цієї утиліти з’являється такий інтерфейс:
![]() |
У полі (1) вводимо назву потрібного класу. У полі (2) з’являються різні можливі варіанти. Вибираємо відповідний, і в полі (3) отримуємо результат — у даному випадку клас HashTable. Цей метод підходить, якщо відома назва класу, який шукаємо. Якщо ж хочемо переглянути перелік можливостей, що пропонує платформа .NET, можна скористатися файлами HTML та StartHere.htm, які також знаходяться безпосередньо в папці інсталяції SSK.Net, наприклад C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

Посилання .NET Framework SDK Documentation — це те, за яким слід перейти, щоб отримати загальний огляд класів .NET:

Тут слід перейти за посиланням [Bibliothèque de classes]. Там міститься перелік усіх класів .NET:

Перейдемо, наприклад, за посиланням System.Collections. Цей простір імен об’єднує різні класи, що реалізують колекції, серед яких клас HashTable:

Перейдемо за посиланням HashTable нижче:

Ми потрапляємо на таку сторінку:

Зверніть увагу на положення курсора нижче. Він вказує на посилання, яке дозволяє вказати бажану мову програмування, в даному випадку Visual Basic.
Там міститься прототип класу, а також приклади його використання. Перейдімо за посиланням [Hashtable, membres] нижче:

Ми отримуємо повний опис класу:

Цей метод є найкращим для ознайомлення з SDK та його класами. Інструмент WinCV виявляється корисним, коли ви вже трохи знайомі з класом, але забули деякі з його членів. WinCV дозволяє швидко знайти клас та його члени.
4.2. Пошук допомоги щодо класів за допомогою VS.NET
Тут ми наводимо кілька вказівок щодо пошуку допомоги з Visual Studio.NET
4.2.1. Пункт меню «Довідка»
Виберімо пункт [?] у меню.

З’явиться таке вікно:

У випадаючому списку можна вибрати фільтр довідки. Тут ми виберемо фільтр [Visual Basic].

Корисні дві довідки:
- довідка щодо самої мови VB.NET (синтаксис)
- довідка щодо classes.NET, які можна використовувати в мові VB.NET
Довідку щодо мови VB.NET можна переглянути через [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic]:

Відкриється така сторінка довідки:

Звідти за допомогою різних підрозділів можна отримати довідку з різних тем, пов’язаних із VB.NET. Зверніть увагу на навчальні матеріали щодо VB.NET:

Щоб отримати доступ до різних класів платформи .NET, слід вибрати довідку [Visual Studio.NET/.NET Framework].

Зокрема, звернемо увагу на розділ [Référence/Bibliothèque de classes]:

Припустимо, що нас цікавить клас [ArrayList]. Він знаходиться в просторі імен [System.Collections]. Це потрібно знати, інакше краще скористатися методом пошуку, описаним нижче. Ми отримаємо таку довідку:

Посилання [ArrayList, classe] надає загальний огляд класу:

Такі сторінки існують для всіх класів. Вони містять короткий опис класу з прикладами. Щоб ознайомитися з описом членів класу, перейдіть за посиланням [ArrayList, membres]:

4.2.2. Довідка/Індекс

Опція [Aide/index] дозволяє знайти допомогу, яка є більш цілеспрямованою, ніж попередня. Достатньо ввести ключове слово, яке шукаєте:

Перевага цього методу порівняно з попереднім полягає в тому, що не потрібно знати, де саме в системі довідки знаходиться те, що ви шукаєте. Ймовірно, цей метод є кращим для цілеспрямованого пошуку, тоді як інший метод більше підходить для ознайомлення з усім, що пропонує довідка.
4.3. Клас String
Клас String має багато властивостей і методів. Ось деякі з них:
кількість символів у рядку | |
властивість, індексована за замовчуванням. [String].Chars(i) — це символ № i у рядку | |
повертає «true», якщо рядок закінчується значенням | |
повертає «true», якщо рядок починається зі значення | |
повертає «true», якщо рядок дорівнює value | |
повертає першу позицію в рядку value — пошук починається з символу № 0 | |
повертає першу позицію в рядку value — пошук починається з символу № startIndex | |
метод класу — повертає рядок, що є результатом об'єднання елементів масиву value з роздільником separator | |
повертає копію поточного рядка, в якому символ oldChar замінено на символ newChar | |
рядок розглядається як послідовність полів, розділених символами, що містяться в масиві separator. Результатом є масив цих полів | |
підрядок поточного рядка, що починається з позиції startIndex і має довжину length символів | |
перетворює поточний рядок на малі літери | |
перетворює поточний рядок на великі літери | |
видаляє пробіли на початку та в кінці поточного рядка |
Рядок C можна розглядати як масив символів. Отже
- C.Chars(i) — це i-й символ у C
- C.Length — кількість символів у C
Розглянемо такий приклад:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Module test
Sub Main()
Dim uneChaine As String = "l'oiseau vole au-dessus des nuages"
affiche("uneChaine=" + uneChaine)
affiche("uneChaine.Length=" & uneChaine.Length)
affiche("chaine[10]=" + uneChaine.Chars(10))
affiche("uneChaine.IndexOf(""vole"")=" & uneChaine.IndexOf("vole"))
affiche("uneChaine.IndexOf(""x"")=" & uneChaine.IndexOf("x"))
affiche("uneChaine.LastIndexOf('a')=" & uneChaine.LastIndexOf("a"c))
affiche("uneChaine.LastIndexOf('x')=" & uneChaine.LastIndexOf("x"c))
affiche("uneChaine.Substring(4,7)=" + uneChaine.Substring(4, 7))
affiche("uneChaine.ToUpper()=" + uneChaine.ToUpper())
affiche("uneChaine.ToLower()=" + uneChaine.ToLower())
affiche("uneChaine.Replace('a','A')=" + uneChaine.Replace("a"c, "A"c))
Dim champs As String() = uneChaine.Split(Nothing)
Dim i As Integer
For i = 0 To champs.Length - 1
affiche("champs[" & i & "]=[" & champs(i) & "]")
Next i
affiche("Join("":"",champs)=" + System.String.Join(":", champs))
affiche("("" abc "").Trim()=[" + " abc ".Trim() + "]")
End Sub
' виводить
Sub affiche(ByVal msg As [String])
' відображає повідомлення
Console.Out.WriteLine(msg)
End Sub
End Module
Виконання дає такі результати:
dos>vbc string1.vb
dos>string1
uneChaine=l'oiseau vole au-dessus des nuages
uneChaine.Length=34
chaine[10]=o
uneChaine.IndexOf("vole")=9
uneChaine.IndexOf("x")=-1
uneChaine.LastIndexOf('a')=30
uneChaine.LastIndexOf('x')=-1
uneChaine.Substring(4,7)=seau vo
uneChaine.ToUpper()=L'OISEAU VOLE AU-DESSUS DES NUAGES
uneChaine.ToLower()=l'oiseau vole au-dessus des nuages
uneChaine.Replace('a','A')=l'oiseAu vole Au-dessus des nuAges
champs[0]=[l'oiseau]
champs[1]=[vole]
champs[2]=[au-dessus]
champs[3]=[des]
champs[4]=[nuages]
Join(":",champs)=l'oiseau:vole:au-dessus:des:nuages
(" abc ").Trim()=[abc]
Розглянемо новий приклад:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Module string2
Sub Main()
' рядок для аналізу
Dim ligne As String = "un:deux::trois:"
' роздільники полів
Dim séparateurs() As Char = {":"c}
' розділення
Dim champs As String() = ligne.Split(séparateurs)
Dim i As Integer
For i = 0 To champs.Length - 1
Console.Out.WriteLine(("Champs[" & i & "]=" & champs(i)))
Next i
' об'єднання
Console.Out.WriteLine(("join=[" + System.String.Join(":", champs) + "]"))
End Sub
End Module
та результати виконання:
Метод Split класу String дозволяє розмістити поля символьного рядка в масиві. Визначення методу, що використовується тут, є таким:
масив символів. Ці символи відповідають тим, що використовуються для розділення полів у символьному рядку. Так, якщо рядок має вигляд [champ1, champ2, champ3], можна використовувати separator=new char() {","c}. Якщо роздільником є послідовність пробілів, слід використовувати separator=nothing. | |
масив рядків, де кожен елемент є полем рядка. |
Метод Join є статичним методом класу String:
масив символьних рядків | |
рядок, який слугуватиме роздільником полів | |
рядок, утворений об'єднанням елементів масиву value, розділених рядком separator. |
4.4. Клас Array
Клас Array реалізує масив. У нашому прикладі ми будемо використовувати такі властивості та методи:
властивість — кількість елементів масиву | |
метод класу — повертає позицію value у відсортованому масиві array — шукає, починаючи з позиції index, і з length елементами | |
метод класу — копіює елементи length з sourceArray у destinationArray — при цьому створюється destinationArray | |
метод класу — сортує масив array — він повинен містити тип даних із функцією сортування за замовчуванням (рядки, числа). |
Наступна програма ілюструє використання класу Array:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Module test
Sub Main()
' зчитування елементів масиву, введених з клавіатури
Dim terminé As [Boolean] = False
Dim i As Integer = 0
Dim éléments1 As Double() = Nothing
Dim éléments2 As Double() = Nothing
Dim élément As Double = 0
Dim réponse As String = Nothing
Dim erreur As [Boolean] = False
While Not terminé
' запитання
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' зчитування відповіді
réponse = Console.ReadLine().Trim()
' завершення введення, якщо рядок порожній
If réponse.Equals("") Then
Exit While
End If
' перевірка введених даних
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' якщо помилок немає
If Not erreur Then
' створення нового масиву для нового елемента
éléments2 = New Double(i) {}
' копіювання старого масиву в новий масив
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' новий масив стає старим масивом
éléments1 = éléments2
' новий масив більше не потрібен
éléments2 = Nothing
' вставлення нового елемента
éléments1(i) = élément
' ще один елемент у масиві
i += 1
End If
End While
' відображення несортованого масиву
System.Console.Out.WriteLine("Tableau non trié")
For i = 0 To éléments1.Length - 1
Console.Out.WriteLine(("éléments[" & i & "]=" & éléments1(i)))
Next i
' сортування таблиці
System.Array.Sort(éléments1)
' відображення відсортованої таблиці
System.Console.Out.WriteLine("Tableau trié")
For i = 0 To éléments1.Length - 1
Console.Out.WriteLine(("éléments[" & i & "]=" & éléments1(i)))
Next i
' Пошук
While Not terminé
' запитання
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' прочитати та перевірити відповідь
réponse = Console.ReadLine().Trim()
' закінчено?
If réponse.Equals("") Then
Exit While
End If
' перевірка
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' якщо помилок немає
If Not erreur Then
' шукаємо елемент у відсортованому масиві
i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
' Виведення відповіді
If i >= 0 Then
Console.Out.WriteLine(("Trouvé en position " & i))
Else
Console.Out.WriteLine("Pas dans le tableau")
End If
End If
End While
End Sub
End Module
Результати виведення на екран такі:
Elément (réel) 0 du tableau (rien pour terminer) : 10,4
Elément (réel) 1 du tableau (rien pour terminer) : 5,2
Elément (réel) 2 du tableau (rien pour terminer) : 8,7
Elément (réel) 3 du tableau (rien pour terminer) : 3,6
Elément (réel) 4 du tableau (rien pour terminer) :
Tableau non trié
éléments[0]=10,4
éléments[1]=5,2
éléments[2]=8,7
éléments[3]=3,6
Tableau trié
éléments[0]=3,6
éléments[1]=5,2
éléments[2]=8,7
éléments[3]=10,4
Elément cherché (rien pour arrêter) : 8,7
Trouvé en position 2
Elément cherché (rien pour arrêter) : 11
Pas dans le tableau
Elément cherché (rien pour arrêter) : a
Saisie incorrecte, recommencez
Elément cherché (rien pour arrêter) :
У першій частині програми створюється масив на основі числових даних, введених з клавіатури. Розмір масиву неможливо визначити заздалегідь, оскільки невідомо, скільки елементів введе користувач. Тому ми працюємо з двома масивами éléments1 та éléments2.
' новий масив для розміщення нового елемента
éléments2 = New Double(i) {}
' копіювання старого масиву в новий масив
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' новий масив стає старим масивом
éléments1 = éléments2
' новий масив більше не потрібен
éléments2 = Nothing
' вставлення нового елемента
éléments1(i) = élément
' ще один елемент у таблиці
i += 1
Масив éléments1 містить значення, введені на даний момент. Коли користувач додає нове значення, створюється масив éléments2, який має на один елемент більше, ніж éléments1, вміст éléments1 копіюється в éléments2 (Array.Copy), направляємо «посилання» éléments1 на éléments2 і, нарешті, додаємо новий елемент до éléments1. Це складний процес, який можна спростити, якщо замість масиву фіксованого розміру (Array) використовувати масив змінного розміру (ArrayList).
Масив сортується за допомогою методу Array.Sort. Цей метод можна викликати з різними параметрами, що визначають правила сортування. Без параметрів за замовчуванням виконується сортування за зростанням. Нарешті, метод Array.BinarySearch дозволяє шукати елемент у відсортованому масиві.
4.5. Клас ArrayList
Клас ArrayList дозволяє реалізовувати масиви змінного розміру під час виконання програми, чого не дозволяє попередній клас Array. Ось деякі з поширених властивостей та методів:
створює порожній список | |
кількість елементів у колекції | |
додає об’єкт value в кінець колекції | |
очищає список | |
індекс елемента value у списку або -1, якщо його немає | |
те саме, але з пошуком, починаючи з елемента № startIndex | |
те саме, але повертає індекс останнього входження значення у списку | |
те саме, але з пошуком, починаючи з елемента № startIndex | |
видалити об’єкт obj, якщо він є у списку | |
видаляє елемент з індексом із списку | |
повертає позицію об’єкта value у списку або -1, якщо його там немає. Список має бути відсортований | |
сортує список. Список повинен містити об’єкти з попередньо визначеним порядком (рядки, числа) | |
сортує список відповідно до порядку, встановленого функцією порівняння |
Повернемося до прикладу, розглянутого з об’єктами типу Array, і розглянемо його з об’єктами типу ArrayList:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Module test
Sub Main()
' читання елементів масиву, введених з клавіатури
Dim terminé As [Boolean] = False
Dim i As Integer = 0
Dim éléments As New ArrayList
Dim élément As Double = 0
Dim réponse As String = Nothing
Dim erreur As [Boolean] = False
While Not terminé
' питання
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' зчитування відповіді
réponse = Console.ReadLine().Trim()
' завершення введення, якщо рядок порожній
If réponse.Equals("") Then
Exit While
End If
' перевірка введених даних
Try
élément = Double.Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' якщо помилок немає
If Not erreur Then
' ще один елемент у масиві
éléments.Add(élément)
End If
End While
' виведення несортованого масиву
System.Console.Out.WriteLine("Tableau non trié")
For i = 0 To éléments.Count - 1
Console.Out.WriteLine(("éléments[" & i & "]=" & éléments(i).ToString))
Next i ' tri du tableau
éléments.Sort()
' виведення відсортованого масиву
System.Console.Out.WriteLine("Tableau trié")
For i = 0 To éléments.Count - 1
Console.Out.WriteLine(("éléments[" & i & "]=" & éléments(i).ToString))
Next i
' Пошук
While Not terminé
' питання
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' прочитати та перевірити відповідь
réponse = Console.ReadLine().Trim()
' закінчено?
If réponse.Equals("") Then
Exit While
End If
' перевірка
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' якщо помилок немає
If Not erreur Then
' шукаємо елемент у відсортованому масиві
i = éléments.BinarySearch(élément)
' Виведення відповіді
If i >= 0 Then
Console.Out.WriteLine(("Trouvé en position " & i))
Else
Console.Out.WriteLine("Pas dans le tableau")
End If
End If
End While
End Sub
End Module
Результати виконання такі:
Elément (réel) 0 du tableau (rien pour terminer) : 10,4
Elément (réel) 0 du tableau (rien pour terminer) : 5,2
Elément (réel) 0 du tableau (rien pour terminer) : a
Saisie incorrecte, recommencez
Elément (réel) 0 du tableau (rien pour terminer) : 3,7
Elément (réel) 0 du tableau (rien pour terminer) : 15
Elément (réel) 0 du tableau (rien pour terminer) :
Tableau non trié
éléments[0]=10,4
éléments[1]=5,2
éléments[2]=3,7
éléments[3]=15
Tableau trié
éléments[0]=3,7
éléments[1]=5,2
éléments[2]=10,4
éléments[3]=15
Elément cherché (rien pour arrêter) : a
Saisie incorrecte, recommencez
Elément cherché (rien pour arrêter) : 15
Trouvé en position 3
Elément cherché (rien pour arrêter) : 1
Pas dans le tableau
Elément cherché (rien pour arrêter) :
4.6. Клас Hashtable
Клас Hashtable дозволяє реалізувати словник. Словник можна уявити як таблицю з двома стовпцями:
![]() |
Ключі є унікальними, c.a.d, тобто не може бути двох однакових ключів. Основні методи та властивості класу Hashtable такі:
створює порожній словник | |
додає рядок (key, value) до словника, де key та value є посиланнями на об’єкти. | |
видаляє зі словника рядок з ключем key | |
очищає словник | |
повертає значення «true», якщо ключ key є у словнику. | |
повертає значення «true», якщо значення value належить до словника. | |
властивість: кількість елементів словника (ключ, значення) | |
властивість: набір ключів словника | |
властивість: набір значень словника | |
індексована властивість: дозволяє дізнатися або встановити значення, пов’язане з ключем key |
Розглянемо таку прикладну програму:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Module test
Sub Main()
Dim liste() As [String] = {"jean:20", "paul:18", "mélanie:10", "violette:15"}
Dim i As Integer
Dim champs As [String]() = Nothing
Dim séparateurs() As Char = {":"c}
' заповнення словника
Dim dico As New Hashtable
For i = 0 To liste.Length - 1
champs = liste(i).Split(séparateurs)
dico.Add(champs(0), champs(1))
Next i
' кількість елементів у словнику
Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
' список ключів
Console.Out.WriteLine("[Liste des clés]")
Dim clés As IEnumerator = dico.Keys.GetEnumerator()
While clés.MoveNext()
Console.Out.WriteLine(clés.Current)
End While
' список значень
Console.Out.WriteLine("[Liste des valeurs]")
Dim valeurs As IEnumerator = dico.Values.GetEnumerator()
While valeurs.MoveNext()
Console.Out.WriteLine(valeurs.Current)
End While
' список ключів та значень
Console.Out.WriteLine("[Liste des clés & valeurs]")
clés.Reset()
While clés.MoveNext()
Console.Out.WriteLine(("clé=" & clés.Current.ToString & " valeur=" & dico(clés.Current).ToString))
End While
' видаляємо ключ «paul»
Console.Out.WriteLine("[Suppression d'une clé]")
dico.Remove("paul")
' список ключів та значень
Console.Out.WriteLine("[Liste des clés & valeurs]")
clés = dico.Keys.GetEnumerator()
While clés.MoveNext()
Console.Out.WriteLine(("clé=" & clés.Current.ToString & " valeur=" & dico(clés.Current).ToString))
End While
' пошук у словнику
Dim nomCherché As [String] = Nothing
Console.Out.Write("Nom recherché (rien pour arrêter) : ")
nomCherché = Console.ReadLine().Trim()
Dim value As [Object] = Nothing
While Not nomCherché.Equals("")
If dico.ContainsKey(nomCherché) Then
value = dico(nomCherché)
Console.Out.WriteLine((nomCherché + "," + CType(value, [String])))
Else
Console.Out.WriteLine(("Nom " + nomCherché + " inconnu"))
End If
' наступний пошук
Console.Out.Write("Nom recherché (rien pour arrêter) : ")
nomCherché = Console.ReadLine().Trim()
End While
End Sub
End Module
Результати виконання такі:
Le dictionnaire a 4 éléments
[Liste des clés]
mélanie
paul
violette
jean
[Liste des valeurs]
10
18
15
20
[Liste des clés & valeurs]
clé=mélanie valeur=10
clé=paul valeur=18
clé=violette valeur=15
clé=jean valeur=20
[Suppression d'une clé]
[Liste des clés & valeurs]
clé=mélanie valeur=10
clé=violette valeur=15
clé=jean valeur=20
Nom recherché (rien pour arrêter) : paul
Nom paul inconnu
Nom recherché (rien pour arrêter) : mélanie
mélanie,10
Nom recherché (rien pour arrêter) :
Програма також використовує об’єкт IEnumerator для перегляду колекцій ключів та значень словника типу ICollection (див. вище властивості Keys та Values). Колекція — це сукупність об’єктів, яку можна переглядати. Інтерфейс ICollection визначено так:

Властивість Count дозволяє дізнатися кількість елементів у колекції. Інтерфейс ICollection походить від інтерфейсу IEnumerable:

Цей інтерфейс має лише один метод GetEnumerator, який дозволяє отримати об’єкт типу IEnumerator:

Метод GetEnumerator() колекції ICollection дозволяє нам перебирати колекцію за допомогою таких методів:
переміщує курсор на наступний елемент колекції. Повертає значення true, якщо цей елемент існує, і false — якщо ні. Перший виклик MoveNext переміщує курсор на перший елемент. «Поточний» елемент колекції тоді доступний у властивості Current перелічувача | |
властивість: поточний елемент колекції | |
переміщує індекс на початок колекції, c.a.d, перед першим елементом. |
Отже, структура ітерації по елементах колекції (ICollection) на мові C виглядає наступним чином:
' визначити колекцію
dim C as ICollection C=...
' отримати індексер цієї колекції
dim itérateur as IEnumerator=C.GetEnumerator();
' пробіг по колекції за допомогою цього індексатора
while(itérateur.MoveNext())
' маємо поточний елемент
' використати itérateur.Current
end while
4.7. Клас StreamReader
Клас StreamReader дозволяє читати вміст файлу. Ось деякі з його властивостей та методів:
відкриває потік з файлу path. Якщо файл не існує, генерується виняток | |
закриває потік | |
зчитує рядок із відкритого потоку | |
зчитує решту потоку, починаючи з поточної позиції |
Ось приклад:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.IO
Module test
Sub Main()
Dim ligne As String = Nothing
Dim fluxInfos As StreamReader = Nothing
' читання вмісту файлу
Try
fluxInfos = New StreamReader("infos.txt")
ligne = fluxInfos.ReadLine()
While Not (ligne Is Nothing)
System.Console.Out.WriteLine(ligne)
ligne = fluxInfos.ReadLine()
End While
Catch e As Exception
System.Console.Error.WriteLine("L'erreur suivante s'est produite : " & e.ToString)
Finally
Try
fluxInfos.Close()
Catch
End Try
End Try
End Sub
End Module
та результати виконання:
dos>more infos.txt
12620:0:0
13190:0,05:631
15640:0,1:1290,5
24740:0,15:2072,5
31810:0,2:3309,5
39970:0,25:4900
48360:0,3:6898,5
55790:0,35:9316,5
92970:0,4:12106
127860:0,45:16754,5
151250:0,5:23147,5
172040:0,55:30710
195000:0,6:39312
0:0,65:49062
dos>file1
12620:0:0
13190:0,05:631
15640:0,1:1290,5
24740:0,15:2072,5
31810:0,2:3309,5
39970:0,25:4900
48360:0,3:6898,5
55790:0,35:9316,5
92970:0,4:12106
127860:0,45:16754,5
151250:0,5:23147,5
172040:0,55:30710
195000:0,6:39312
0:0,65:49062
4.8. Клас StreamWriter
Клас StreamWriter дозволяє записувати дані у файл. Ось деякі з його властивостей та методів:
відкриває потік запису з файлу path. Якщо файл не вдається створити, генерується виняток | |
якщо значення дорівнює true, запис у потік відбувається без використання буфера; в іншому випадку запис у потік не відбувається негайно: спочатку дані записуються в буфер, а потім — у потік, коли буфер заповнюється. За замовчуванням використовується режим з буфером. Він добре підходить для файлових потоків, але, як правило, не підходить для мережевих потоків. | |
щоб встановити або дізнатися маркер кінця рядка, який має використовуватися методом WriteLine | |
закриває потік | |
записує рядок у потік запису | |
записує вміст буфера в потік |
Розглянемо такий приклад:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.IO
Module test
Sub Main()
Dim ligne As String = Nothing ' une ligne de texte
Dim fluxInfos As StreamWriter = Nothing ' le fichier texte
Try
' створення текстового файлу
fluxInfos = New StreamWriter("infos.txt")
' читання рядка, введеного з клавіатури
Console.Out.Write("ligne (rien pour arrêter) : ")
ligne = Console.In.ReadLine().Trim()
' цикл, поки введений рядок не є порожнім
While ligne <> ""
' запис рядка у текстовий файл
fluxInfos.WriteLine(ligne)
' читання нового рядка з клавіатури
Console.Out.Write("ligne (rien pour arrêter) : ")
ligne = Console.In.ReadLine().Trim()
End While
Catch e As Exception
System.Console.Error.WriteLine("L'erreur suivante s'est produite : " & e.ToString)
Finally
' закриття файлу
Try
fluxInfos.Close()
Catch
End Try
End Try
End Sub
End Module
та результати виконання:
dos>file2
ligne (rien pour arrêter) : ligne1
ligne (rien pour arrêter) : ligne2
ligne (rien pour arrêter) : ligne3
ligne (rien pour arrêter) :
dos>more infos.txt
ligne1
ligne2
ligne3
4.9. Клас Regex
Клас Regex дозволяє використовувати регулярні вирази. Вони дають змогу перевіряти формат символьного рядка. Таким чином можна перевірити, чи рядок, що позначає дату, має формат дд/мм/рр. Для цього використовується шаблон, з яким порівнюється рядок. Отже, у цьому прикладі символи j, m та a мають бути цифрами. Шаблон дійсного формату дати має вигляд «\d\d/\d\d/\d\d», де символ \d позначає цифру. У шаблоні можна використовувати такі символи (документація Microsoft):
Опис | |
Позначає наступний символ як спеціальний або літеральний. Наприклад, «n» відповідає символу «n». «\n» відповідає символу нового рядка. Послідовність «\\» відповідає «\», а «\(" відповідає «(». | |
Відповідає початку введення. | |
Відповідає кінцю введення. | |
Відповідає попередньому символу нуль або більше разів. Таким чином, «zo*» відповідає «z» або «zoo». | |
Відповідає попередньому символу один або кілька разів. Таким чином, «zo+» відповідає «zoo», але не «z». | |
Відповідає попередньому символу нуль або один раз. Наприклад, «a?ve?» відповідає «ve» у слові «lever». | |
Відповідає будь-якому окремому символу, крім символу нового рядка. | |
| Здійснює пошук за modèle і запам'ятовує збіг. Відповідний підрядок можна витягти з отриманої колекції Matches за допомогою елемента [0]...[n]. Щоб знайти збіги з символами в дужках ( ), використовуйте "\(" або "\)". |
| Відповідає або x, або y. Наприклад, «z|foot» відповідає «z» або «foot». «(z|f)oo» відповідає «zoo» або «foo». |
| n — це невід’ємне ціле число. Відповідає точно n, помноженому на символ. Наприклад, «o{2}» не відповідає «o» у слові «Bob», а відповідає двом першим «o» у слові «fooooot». |
| n — це невід’ємне ціле число. Відповідає щонайменше n-кратному кількості символів. Наприклад, «o{2,}» не відповідає «o» у слові «Bob», а відповідає всім «o» у слові «fooooot». «o{1,}» еквівалентно «o+», а «o{0,}» — «o*». |
| m та n — це невід’ємні цілі числа. Відповідає щонайменше n і щонайбільше m повторень символу. Наприклад, «o{1,3}» відповідає трьом першим «o» у слові «foooooot», а «o{0,1}» дорівнює «o?». |
| Набір символів. Відповідає одному з вказаних символів. Наприклад, «[abc]» відповідає «a» у слові «plat». |
| Негативний набір символів. Відповідає будь-якому символу, що не вказано. Наприклад, «[^abc]» відповідає «p» у слові «plat». |
| Діапазон символів. Відповідає будь-якому символу у вказаному діапазоні. Наприклад, «[a-z]» відповідає будь-якій маленькій літері від «a» до «z». |
| Негативний діапазон символів. Відповідає будь-якому символу, якого немає у вказаній послідовності. Наприклад, «[^m-z]» відповідає будь-якому символу, якого немає між «m» і «z». |
Відповідає межі, що позначає слово, іншими словами, позиції між словом і пробілом. Наприклад, «er\b» відповідає «er» у слові «lever», але не «er» у слові «verbe». | |
Відповідає межі, що не представляє слова. «en*t\B» відповідає «ent» у слові «bien entendu». | |
Відповідає символу, що позначає цифру. Еквівалентно [0-9]. | |
Відповідає символу, що не є цифрою. Еквівалентно [^0-9]. | |
Відповідає символу переходу на новий рядок. | |
Відповідає символу нового рядка. | |
Відповідає символу повернення каретки. | |
Відповідає будь-якому пробілу, включаючи пробіл, табуляцію, перехід на новий аркуш тощо. Еквівалентно «[ \f\n\r\t\v]». | |
Відповідає будь-якому символу, що не є пробілом. Еквівалентно «[^ \f\n\r\t\v]». | |
Відповідає символу табуляції. | |
Відповідає символу вертикального табуляції. | |
Відповідає будь-якому символу, що позначає слово та містить підкреслення. Еквівалентно «[A-Za-z0-9_]». | |
Відповідає будь-якому символу, що не позначає слово. Еквівалентно «[^A-Za-z0-9_]». | |
| Відповідає num, де num — це додатне ціле число. Посилається на збережені відповідності. Наприклад, «(.)\1» відповідає двом послідовним однаковим символам. |
| Відповідає n, де n — це вісімкове значення екранування. Вісімкові значення екранування повинні складатися з 1, 2 або 3 цифр. Наприклад, «\11» і «\011» обидва відповідають символу табуляції. "\0011" еквівалентно "\001" & "1". Восьмиричні екрануючі значення не повинні перевищувати 256. Якщо це сталося, у виразі враховуватимуться лише перші дві цифри. Дозволяє використовувати коди ASCII у регулярних виразах. |
| Відповідає n, де n — це шістнадцяткове значення екранування. Шістнадцяткові екрануючі значення обов’язково мають складатися з двох цифр. Наприклад, «\x41» відповідає «A». «\x041» дорівнює «\x04» та «1». Дозволяє використовувати коди ASCII у регулярних виразах. |
Елемент у шаблоні може зустрічатися один або кілька разів. Розглянемо кілька прикладів із символом \d, який позначає 1 цифру:
модель | значення |
цифра | |
0 або 1 цифра | |
0 або більше цифр | |
1 або більше цифр | |
2 цифри | |
щонайменше 3 цифри | |
від 5 до 7 цифр |
Тепер уявімо модель, здатну описати очікуваний формат рядка символів:
пошуковий рядок | модель |
\d{2}/\d{2}/\d{2} | |
\d{2}:\d{2}:\d{2} | |
\d+ | |
\s* | |
\s*\d+\s* | |
\s*[+|-]?\s*\d+\s* | |
\s*\d+(.\d*)?\s* | |
\s*[+|]?\s*\d+(.\d*)?\s* | |
\bjuste\b | |
Можна вказати, де саме в рядку шукати шаблон:
шаблон | значення |
модель починає рядок | |
модель закінчує рядок | |
шаблон починає та закінчує рядок | |
шаблон шукається по всьому рядку, починаючи з його початку. |
шуканий рядок | шаблон |
!$ | |
\.$ | |
^// | |
^\s*\w+\s*$ | |
^\s*\w+\s*\w+\s*$ | |
\bsecret\b |
Підмножини шаблону можна «витягувати». Таким чином, можна не тільки перевірити, чи рядок відповідає певному шаблону, але й витягнути з цього рядка елементи, що відповідають підмножинам шаблону, які були взяті в дужки. Отже, якщо ми аналізуємо рядок, що містить дату дд/мм/рр, і хочемо додатково виокремити елементи дд, мм, рр з цієї дати, ми використаємо шаблон (\d\d)/(\d\d)/(\d\d).
4.9.1. Перевірка відповідності рядка заданому шаблону
Об’єкт типу Regex створюється таким чином:
Конструктор створює об’єкт «регулярний вираз» на основі шаблону, переданого як параметр (pattern). Після створення шаблону регулярного виразу його можна порівняти з символьними рядками за допомогою методу IsMatch:
IsMatch повертає значення «true», якщо вхідний рядок відповідає шаблону регулярного виразу. Ось приклад:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex1
Sub Main()
' шаблон регулярного виразу
Dim modèle1 As String = "^\s*\d+\s*$"
Dim regex1 As New Regex(modèle1)
' порівняння екземпляра з шаблоном
Dim exemplaire1 As String = " 123 "
If regex1.IsMatch(exemplaire1) Then
affiche(("[" + exemplaire1 + "] correspond au modèle [" + modèle1 + "]"))
Else
affiche(("[" + exemplaire1 + "] ne correspond pas au modèle [" + modèle1 + "]"))
End If
Dim exemplaire2 As String = " 123a "
If regex1.IsMatch(exemplaire2) Then
affiche(("[" + exemplaire2 + "] correspond au modèle [" + modèle1 + "]"))
Else
affiche(("[" + exemplaire2 + "] ne correspond pas au modèle [" + modèle1 + "]"))
End If
End Sub
' вивести
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
та результати виконання:
dos>vbc /r:system.dll regex1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>regex1
[ 123 ] correspond au modèle [^\s*\d+\s*$]
[ 123a ] ne correspond pas au modèle [^\s*\d+\s*$]
4.9.2. Знайти всі елементи рядка, що відповідають шаблону
Метод Matches
повертає колекцію елементів рядка input, що відповідають шаблону, як показано в наступному прикладі:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' кілька входжень шаблону в екземплярі
Dim modèle2 As String = "\d+"
Dim regex2 As New Regex(modèle2) '
Dim exemplaire3 As String = " 123 456 789 "
Dim résultats As MatchCollection = regex2.Matches(exemplaire3)
affiche(("Modèle=[" + modèle2 + "],exemplaire=[" + exemplaire3 + "]"))
affiche(("Il y a " & résultats.Count & " occurrences du modèle dans l'exemplaire "))
Dim i As Integer
For i = 0 To résultats.Count - 1
affiche((résultats(i).Value & " en position " & résultats(i).Index))
Next i
End Sub
'відображає
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
Клас MatchCollection має властивість Count, яка позначає кількість елементів у колекції. Якщо résultats є об’єктом MatchCollection, то résultats(i) є i-м елементом цієї колекції та має тип Match. У нашому прикладі résultats — це сукупність елементів ланцюжка exemplaire3, що відповідають шаблону modèle2, а résultats(i) — один із цих елементів. Клас Match має дві властивості, які нас тут цікавлять:
- Value: значення об’єкта Match, тобто елемента, що відповідає моделі
- Index: позиція, на якій елемент було знайдено в обробленому рядку
Результати виконання попередньої програми:
dos>vbc /r:system.dll regex2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4p our Microsoft (R) .NET Framework version 1.1.4322.573
dos>regex2
Modèle=[\d+],exemplaire=[ 123 456 789 ]
Il y a 3 occurrences du modèle dans l'exemplaire
123 en position 2
456 en position 7
789 en position 12
4.9.3. Витягнення частин шаблону
Підмножини шаблону можна «витягувати». Таким чином, можна не тільки перевірити, чи відповідає рядок певному шаблону, але й витягнути з цього рядка елементи, що відповідають підмножинам шаблону, які були взяті в дужки. Отже, якщо ми аналізуємо рядок, що містить дату дд/мм/рр, і хочемо додатково виокремити елементи дд, мм, рр з цієї дати, ми використаємо шаблон (\d\d)/(\d\d)/(\d\d). Розглянемо такий приклад:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' вибір елементів у моделі
Dim modèle3 As String = "(\d\d):(\d\d):(\d\d)"
Dim regex3 As New Regex(modèle3)
Dim exemplaire4 As String = "Il est 18:05:49"
' перевірка моделі
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' екземпляр відповідає шаблону
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' відображення груп
Dim i As Integer
For i = 0 To résultat.Groups.Count - 1
affiche(("groupes[" & i & "]=[" & résultat.Groups(i).Value & "] en position " & résultat.Groups(i).Index))
Next i
Else
' екземпляр не відповідає шаблону
affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
End If
End Sub
'відображає
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
Виконання цієї програми дає такі результати:
dos>vbc /r:system.dll regex3.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>regex3
L'exemplaire [Il est 18:05:49] correspond au modèle [(\d\d):(\d\d):(\d\d)]
groupes[0]=[18:05:49] en position 7
groupes[1]=[18] en position 7
groupes[2]=[05] en position 10
groupes[3]=[49] en position 13
Нововведення міститься в наступному фрагменті коду:
' перевірка відповідності зразку
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' екземпляр відповідає шаблону
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' відображаються групи
Dim i As Integer
For i = 0 To résultat.Groups.Count - 1
affiche(("groupes[" & i & "]=[" & résultat.Groups(i).Value & "] en position " & résultat.Groups(i).Index))
Next i
Else
Рядок exemplaire4 порівнюється з шаблоном regex3 за допомогою методу Match. Цей метод повертає об’єкт Match, який вже було представлено. Тут ми використовуємо дві нові властивості цього класу:
- Success: вказує, чи було знайдено збіг
- Groups: колекція, де
- Groups[0] відповідає частині рядка, що відповідає шаблону
- Groups[i] (i>=1) відповідає групі дужок № i
Якщо результат має тип Match, то résultats.Groups має тип GroupCollection, а résultats.Groups[i] — тип Group. Клас Group має дві властивості, які ми використовуємо тут:
- Value: значення об’єкта Group, елемент якого відповідає вмісту дужки
- Index: позиція, на якій елемент було знайдено в обробленому рядку
4.9.4. Програма для навчання
Знайти регулярний вираз, який дозволяє перевірити, чи рядок дійсно відповідає певному шаблону, іноді є справжнім викликом. Наступна програма дозволяє потренуватися. Вона запитує шаблон і рядок, а потім вказує, чи відповідає рядок шаблону чи ні.
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic
Module regex4
Sub Main()
' шаблон регулярного виразу
Dim modèle, chaine As String
Dim regex As Regex = Nothing
Dim résultats As MatchCollection
' запитуються у користувача шаблони та екземпляри, які потрібно порівняти з цим
Dim terminé1 As Boolean = False
Do While Not terminé1
Dim erreur As Boolean = True
Do While Not terminé1 And erreur
' запитується шаблон
Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
modèle = Console.In.ReadLine()
' закінчено?
If modèle.Trim().ToLower() = "fin" Then
terminé1 = True
Else
' створюється регулярний вираз
Try
regex = New Regex(modèle)
erreur = False
Catch ex As Exception
Console.Error.WriteLine(("Erreur : " + ex.Message))
End Try
End If
Loop
' закінчено?
If terminé1 Then Exit Sub
' запитуємо у користувача екземпляри, які потрібно порівняти з шаблоном
Dim terminé2 As Boolean = False
Do While Not terminé2
Console.Out.Write(("Tapez la chaîne à comparer au modèle [" + modèle + "] ou fin pour arrêter :"))
chaine = Console.In.ReadLine()
' завершено?
If chaine.Trim().ToLower() = "fin" Then
terminé2 = True
Else
' виконується порівняння
résultats = regex.Matches(chaine)
' успішно?
If résultats.Count = 0 Then
Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
Else
' відображаються елементи, що відповідають шаблону
Dim i As Integer
For i = 0 To résultats.Count - 1
Console.Out.WriteLine(("J'ai trouvé la correspondance [" & résultats(i).Value & "] en position " & résultats(i).Index))
' піделементи
If résultats(i).Groups.Count <> 1 Then
Dim j As Integer
For j = 1 To (résultats(i).Groups.Count) - 1
Console.Out.WriteLine((ControlChars.Tab & "sous-élément [" & résultats(i).Groups(j).Value & "] en position " & résultats(i).Groups(j).Index))
Next j
End If
Next i
End If
End If
Loop
Loop
End Sub
'відображає
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
Ось приклад виконання:
Tapez le modèle à tester ou fin pour arrêter :\d+
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :123 456 789
J'ai trouvé la correspondance [123] en position 0
J'ai trouvé la correspondance [456] en position 4
J'ai trouvé la correspondance [789] en position 8
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :fin
Tapez le modèle à tester ou fin pour arrêter :(\d\d):(\d\d)
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :14:15 abcd 17:18 xyzt
J'ai trouvé la correspondance [14:15] en position 0
sous-élément [14] en position 0
sous-élément [15] en position 3
J'ai trouvé la correspondance [17:18] en position 11
sous-élément [17] en position 11
sous-élément [18] en position 14
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :fin
Tapez le modèle à tester ou fin pour arrêter :^\s*\d+\s*$
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter : 1456
J'ai trouvé la correspondance [ 1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter :fin
Tapez le modèle à tester ou fin pour arrêter :^\s*(\d+)\s*$
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :1456
J'ai trouvé la correspondance [1456] en position 0
sous-élément [1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :abcd 1
456
Je n'ai pas trouvé de correspondances
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :fin
Tapez le modèle à tester ou fin pour arrêter :fin
4.9.5. Метод Split
Ми вже зустрічали цей метод у класі String:
Рядок розглядається як послідовність полів, розділених символами, що містяться в масиві [separator]. Результатом є масив цих полів.
Роздільником полів у рядку тут є один із символів масиву separator. Метод Split класу Regex дозволяє нам визначити роздільник на основі шаблону:
Рядок [input] розбивається на поля, які розділяються роздільником, що відповідає шаблону поточного об’єкта Regex. Припустимо, наприклад, що в текстовому файлі ми маємо рядки у вигляді поле1, поле2, .., полеn. Поля розділяються комою, але перед нею або після неї можуть бути пробіли. У такому разі метод Split класу string не підходить. Рішенням є метод RegEx. Якщо ligne — це прочитаний рядок, то поля можна отримати за допомогою
як показано в наступному прикладі:
' параметри
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Text.RegularExpressions
Module regex5
Sub Main()
' один рядок
Dim ligne As String = "abc , def , ghi"
' шаблон
Dim modèle As New Regex("\s*,\s*")
' розбиття рядка на поля
Dim champs As String() = modèle.Split(ligne)
' відображення
Dim i As Integer
For i = 0 To champs.Length - 1
Console.Out.WriteLine(("champs[" & i & "]=[" & champs(i) & "]"))
Next i
End Sub
End Module
Результати виконання:
dos>vbc /r:system.dll regex5.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
dos>regex5
champs[0]=[abc]
champs[1]=[def]
champs[2]=[ghi]
4.10. Класи BinaryReader та BinaryWriter
Класи BinaryReader та BinaryWriter призначені для читання та запису бінарних файлів. Розглянемо таку програму. Ми хочемо написати програму, яка викликатиметься наступним чином:
// синтаксис pg text bin
// читання текстового файлу (текст) та збереження його вмісту у
// бінарний файл
// текстовий файл містить рядки у форматі ім'я : вік
// які будуть збережені у структурі string, int
Текстовий файл має такий вміст:
Програма має такий вигляд:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
' BinaryWriter()
Module bw1
' синтаксис pg текст bin
' читаємо текстовий файл (text) і зберігаємо його вміст у
' бінарний файл
' текстовий файл містить рядки у форматі ім'я : вік
' які будуть збережені у структурі string, int
Sub Main(ByVal arguments() As String)
' потрібні 2 аргументи
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg texte binaire")
Environment.Exit(1)
End If
' відкриття текстового файлу для читання
Dim input As StreamReader = Nothing
Try
input = New StreamReader(arguments(0))
Catch ex As Exception
Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(0) & "(" & ex.Message & ")")
Environment.Exit(2)
End Try
' відкриття бінарного файлу для запису
Dim output As BinaryWriter = Nothing
Try
output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))
Catch ex As Exception
Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(1) & "(" & ex.Message & ")")
Environment.Exit(3)
End Try
' читання текстового файлу — запис бінарного файлу
' рядок текстового файлу
Dim ligne As String
' роздільник полів у рядку
Dim séparateur As New Regex("\s*:\s*")
' шаблон віку
Dim modAge As New Regex("\s*\d+\s*")
Dim numLigne As Integer = 0
Dim traitementFini As Boolean
Dim champs As String()
ligne = input.ReadLine()
While Not (ligne Is Nothing)
traitementFini = False
' порожній рядок?
If ligne.Trim() = "" Then
traitementFini = True
End If
' ще один рядок
If Not traitementFini Then
numLigne += 1
' рядок «ім'я: вік»
champs = séparateur.Split(ligne)
' нам потрібно 2 поля
If champs.Length <> 2 Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
' наступний рядок
traitementFini = True
End If
End If
If Not traitementFini Then
' друге поле має бути цілим числом >=0
If Not modAge.IsMatch(champs(1)) Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
' наступний рядок
traitementFini = True
End If
' записуємо дані у двійковий файл
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
End If
'наступний рядок
ligne = input.ReadLine()
End While
' закриття файлів
input.Close()
output.Close()
End Sub
End Module
Зупинимося на операціях, що стосуються класу BinaryWriter:
- об’єкт BinaryWriter відкривається операцією
output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))
Аргументом конструктора має бути потік (Stream). У даному випадку це потік, побудований на основі файлу (FileStream), для якого задано:
- (продовження)
- ім’я
- операцію, яку потрібно виконати, тут FileMode.Create для створення файлу
- тип доступу, у даному випадку FileAccess.Write для доступу до файлу з правом запису
- операцію запису
' дані записуються у двійковий файл
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
Клас BinaryWriter має різні перевантажені методи Write для запису різних типів простих даних
- операція закриття потоку
Результати попереднього виконання нам надасть наступна програма. Вона також приймає два аргументи:
' синтаксис pg bin текст
' читання бінарного файлу bin та збереження його вмісту у текстовому файлі (текст)
' бінарний файл має структуру string, int
' текстовий файл містить рядки у форматі ім'я : вік
Отже, ми виконуємо зворотну операцію. Ми зчитуємо двійковий файл, щоб створити текстовий файл. Якщо отриманий текстовий файл ідентичний вихідному, ми будемо знати, що перетворення «текст → двійковий → текст» пройшло успішно. Код такий:
' опції
Option Strict On
Option Explicit On
' простори імен
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
Module br1
' синтаксис pg bin текст
' зчитується бінарний файл bin, а його вміст записується у текстовий файл (текст)
' бінарний файл має структуру string, int
' текстовий файл містить рядки у форматі ім'я : вік
Sub Main(ByVal arguments() As String)
' потрібні 2 аргументи
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg binaire texte")
Environment.Exit(1)
End If
' відкриття бінарного файлу для читання
Dim dataIn As BinaryReader = Nothing
Try
dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))
Catch ex As Exception
Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(0) & "(" & ex.Message & ")")
Environment.Exit(2)
End Try
' відкриття текстового файлу для запису
Dim dataOut As StreamWriter = Nothing
Try
dataOut = New StreamWriter(arguments(1))
dataOut.AutoFlush = True
Catch ex As Exception
Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(1) & "(" & ex.Message & ")")
Environment.Exit(3)
End Try
' читання бінарного файлу — запис текстового файлу
Dim nom As String ' nom d'une personne
Dim age As Integer ' son âge
' цикл обробки бінарного файлу
While True
' читання імені
Try
nom = dataIn.ReadString()
Catch
' кінець файлу
Exit Sub
End Try
' читання віку
Try
age = dataIn.ReadInt32()
Catch
Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
Exit Sub
End Try
' запис у текстовий файл
dataOut.WriteLine(nom & ":" & age)
System.Console.WriteLine(nom & ":" & age)
End While
' закриваємо все
dataIn.Close()
dataOut.Close()
End Sub
End Module
Зупинимося на операціях, що стосуються класу BinaryReader:
- об’єкт BinaryReader відкривається операцією
dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))
Аргументом конструктора має бути потік (Stream). У цьому випадку це потік, побудований на основі файлу (FileStream), для якого задано:
- (продовження)
- ім’я
- операцію, яку потрібно виконати, тут — FileMode.Open для відкриття існуючого файлу
- тип доступу, у даному випадку FileAccess.Read для доступу до файлу в режимі читання
- операцію читання
Клас BinaryReader має різні методи ReadXX для читання різних типів простих даних
- операція закриття потоку
Якщо виконати дві програми послідовно, перетворюючи personnes.txt на personnes.bin, а потім personnes.bin на personnes.txt2, отримаємо:

