Skip to content

4. 常用类 .NET

本文将介绍 .NET 平台中的一些类,即使对于初学者来说也颇具参考价值。首先,我们将展示如何获取关于数百个可用类的详细信息。

4.1. 使用 SDK.NET 寻求帮助

4.1.1. wincv

如果仅安装了 SDK 而未安装 Visual Studio.NET,则可以使用通常位于 SDK 目录树中的 wincv.exe 程序,例如 C:\Program Files\Microsoft Visual Studio。NET 2003\SDK\v1.1。启动该工具时,将显示以下界面:

在 (1) 处输入所需类的名称。这将显示 (2) 处各种可能的主题。选择合适的主题,结果将显示在 (3) 处,此处为类 HashTable。如果已知要查找的类名,此方法适用。若要浏览 .NET,或者可以使用位于 SSK.Net 安装文件夹(例如 C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

Image

请点击 .NET Framework SDK Documentation 链接,以获取 .NET 类的概览:

Image

在此,我们将点击 [Bibliothèque de classes] 链接。该页面列出了所有 .NET 类:

Image

例如,我们点击链接 System.Collections。该命名空间包含多个实现集合的类,其中包括类 HashTable

Image

接下来我们查看下面的链接 HashTable

Image

我们将看到以下页面:

Image

请注意下图中鼠标指针的位置。它指向一个用于指定所需编程语言的链接,此处为 Visual Basic。

该页面提供了该类的原型以及使用示例。请点击下方的链接 [Hashtable, membres]:

Image

由此可获得该类的完整描述:

Image

这是了解 SDK 及其类别的最佳方法。 当您已对某个类有所了解,但忘记了其中某些成员时,WinCV 工具便派上用场。此时,WinCV 可帮助您快速查找该类及其成员。

4.2. 使用 VS.NET 查找类相关帮助

以下提供一些使用 Visual Studio.NET 查找帮助的指引

4.2.1. “帮助”选项

请选择菜单中的 [?] 选项。

Image

此时将显示以下窗口:

Image

在下拉列表中,可以选择一个帮助过滤器。这里,我们将选择过滤器 [Visual Basic]。

Image

有两项帮助内容非常有用:

  • 关于 VB.NET 语言本身的帮助(语法)
  • 关于VB.NET语言可用的classes.NET帮助

可通过 [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic] 访问 VB.NET 语言帮助:

Image

将显示以下帮助页面:

Image

在此基础上,通过各个子栏目,我们可以获取关于 VB.NET 不同主题的帮助。请特别关注 VB.NET 的教程:

Image

若要访问 .NET 平台的各类课程,请选择 [Visual Studio.NET/.NET Framework] 帮助。

Image

我们将特别关注[Référence/Bibliothèque de classes]这一部分:

Image

假设我们关注类 [ArrayList]。它位于命名空间 [System.Collections] 中。必须了解这一点,否则建议采用下文所述的搜索方法。我们将获得以下帮助信息:

Image

链接 [ArrayList, classe] 提供了该类的概览:

Image

所有类都存在此类页面。该页面提供了该类的摘要及示例。如需查看该类的成员描述,请点击链接 [ArrayList, membres]:

Image

4.2.2. 帮助/索引

Image

选项 [Aide/index] 允许进行比之前更精准的帮助搜索。只需输入要查找的关键词即可:

Image

与前一种方法相比,此方法的优势在于无需了解所查找内容在帮助系统中的具体位置。进行定向搜索时,这可能是更优选的方法,而另一种方法则更适合用于探索帮助文档提供的全部内容。

4.3. String 类

String 类拥有许多属性和方法。以下列举其中部分:

Public ReadOnly Property Length As Integer
字符串的字符数
Public Default ReadOnly Property
Chars(ByVal index As Integer) As Char
默认索引属性。[String].Chars(i) 表示字符串中的第 i 个字符
Public Function EndsWith(ByVal value As String)
As Boolean
如果字符串以 value 结尾,则返回 true
Public Function StartsWith(ByVal value As String)
As Boolean
如果字符串以 value 开头,则返回 true
Overloads Public Function Equals(ByVal value
As String) As Boolean
如果字符串等于 value,则返回 true
Overloads Public Function IndexOf(ByVal value
As String) As Integer
返回字符串中 value 的第一个位置——搜索从第 0 个字符开始
Overloads Public Function IndexOf(ByVal value
As String,ByVal startIndex As Integer) As Integer
返回字符 value 在字符串中的第一个位置——搜索从第 0 个字符开始
Overloads Public Shared Function
Join(ByVal separator As String,ByVal value()
As String) As String
类方法——返回一个字符串,该字符串是将数组 value 的值与分隔符 separator 连接而成的结果
Overloads Public Function Replace(ByVal oldChar
As Char,ByVal newChar As Char) As String
返回当前字符串的副本,其中字符 oldChar 已被字符 newChar 替换
Overloads Public Function Split(ByVal ParamArray
separator() As Char) As String()
将字符串视为由 separator 数组中的字符分隔的一系列字段。结果是这些字段的数组
Overloads Public Function Substring(
ByVal startIndex As Integer,ByVal length As Integer)
As String
当前字符串中从位置 startIndex 开始、长度为 length 个字符的子字符串
Overloads Public Function ToLower()
As String
将当前字符串转换为小写
Overloads Public Function ToUpper()
As String
将当前字符串转换为大写
Overloads Public Function Trim()
As String
去除当前字符串首尾的空格

字符串 C 可以视为一个字符数组。因此

  • C.Chars(i) 表示 C 字符串中的第 i 个字符
  • 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

以及运行结果:

Champs[0]=un
Champs[1]=deux
Champs[2]=
Champs[3]=trois
Champs[4]=
join=[un:deux::trois:]

String 中的 Split 方法可用于将字符串中的字段拆分到数组中。此处使用的该方法定义如下:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()
separator
字符数组。这些字符代表用于分隔字符串中各字段的字符。因此,如果字符串为 [champ1, champ2, champ3],则可使用 separator=new char() {","c}。如果分隔符是一连串空格,则使用 separator=nothing
résultat
字符串数组,其中每个元素都是字符串中的一个字段。

Join 方法是 String 类的静态方法:

Overloads Public Shared Function Join(ByVal separator As String,ByVal value() As String) As String
value
字符串数组
separator
用作字段分隔符的字符串
résultat
由数组 value 的元素连接而成,并以字符串 separator 分隔的字符串。

4.4. Array 类

Array 类实现了数组。在本示例中,我们将使用以下属性和方法:

Public ReadOnly Property Length As Integer
属性 - 数组的元素个数
Overloads Public Shared Function BinarySearch
(ByVal array As Array,ByVal index As Integer,
ByVal length As Integer,ByVal value As Object) As Integer
类方法 - 返回 value 在已排序数组 array 中的位置 - 从位置 index 开始搜索,并包含 length 个元素
Overloads Public Shared Sub Copy(ByVal sourceArray
As Array,ByVal destinationArray As Array,
ByVal length As Integer)
类方法——将 length 中的元素从 sourceArray 复制到 destinationArray——同时创建 destinationArray
Overloads Public Shared Sub Sort(ByVal array As Array)
类方法 - 对数组 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 则不支持此功能。以下是一些常见的属性和方法:

Public Sub New()
构建一个空列表
Public Overridable ReadOnly Property Count
As Integer  Implements ICollection.Count
集合中的元素数量
Public Overridable Function Add(ByVal value
As Object) As Integer Implements IList.Add
将 value 对象添加到集合末尾
Public Overridable Sub Clear()
Implements IList.Clear
清空列表
Overloads Public Overridable Function
IndexOf(ByVal value As Object) As Integer
Implements IList.IndexOf
列表中 value 对象的索引,若不存在则返回 -1
Overloads Public Overridable Function
IndexOf(ByVal value As Object, ByVal startIndex
As Integer) As Integer
同上,但从第 n 号元素开始搜索 startIndex
Overloads Public Overridable Function
LastIndexOf(ByVal value As Object) As Integer
同上,但返回列表中 value 的最后一次出现索引
Overloads Public Overridable Function
LastIndexOf(ByVal value As Object, ByVal startIndex As Integer) As Integer
同上,但从第 n 号元素开始搜索startIndex
Public Overridable Sub Remove( ByVal obj As Object)
Implements IList.Remove
如果列表中存在该对象,则将其移除
Public Overridable Sub RemoveAt(ByVal index As Integer)
Implements IList.RemoveAt
从列表中移除索引为 index 的元素
Overloads Public Overridable Function
BinarySearch(ByVal value As Object) As Integer
返回列表中 value 对象的位置,若不存在则返回 -1。列表必须已排序
Overloads Public Overridable Sub Sort()
对列表进行排序。该列表必须包含具有预定义排序关系的对象(字符串、数字)
Overloads Public Overridable Sub
Sort(ByVal comparer As IComparer)
根据由比较函数建立的排序关系对列表进行排序

让我们重新审视之前使用 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 类的主要方法和属性如下:

Public Sub New()
创建一个空字典
Public Overridable Sub Add(ByVal key As
Object,ByVal value As Object)
Implements IDictionary.Add
在字典中添加一行 (key,value),其中 key 和 value 是对象引用。
Public Overridable Sub Remove
(ByVal key As Object) Implements IDictionary.Remove
从字典中删除键为 key 的条目
Public Overridable Sub Clear()
Implements IDictionary.Clear
清空字典
Public Overridable Function ContainsKey
(ByVal key As Object) As Boolean
如果键 key 属于字典,则返回 true。

Public Overridable Function
ContainsValue(ByVal value As Object) As Boolean
如果值 value 属于字典,则返回 true。
Public Overridable ReadOnly Property
Count As Integer  Implements ICollection.Count
属性:字典中(键、值)对的数量
Public Overridable ReadOnly Property
Keys As ICollection Implements IDictionary.Keys
属性:字典键的集合
Public Overridable ReadOnly Property
Values As ICollection Implements IDictionary.Values
属性:字典值的集合
Public Overridable Default Property
Item(ByVal key As Object) As Object  Implements IDictionary.Item
索引属性:用于获取或设置与键 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 接口定义如下:

Image

属性 Count 允许我们获取集合中元素的数量。接口 ICollection 继承自接口 IEnumerable

Image

该接口仅包含一个方法 GetEnumerator,该方法可让我们获取一个类型为 IEnumerator 的对象:

Image

ICollection集合中的GetEnumerator()方法允许我们使用以下方法遍历该集合:

MoveNext
将光标定位到集合中的下一个元素。如果该元素存在,则返回 true;否则返回 false。第一个 MoveNext 将光标定位到第一个元素。此时,集合的“当前”元素可通过枚举器的 Current 属性获取
Current
属性:集合的当前元素
Reset
将迭代器重置到集合开头,即 c.a.d,位于第一个元素之前。

因此,C语言中遍历集合元素(ICollection)的结构如下:

' 定义集合
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 类用于读取文件内容。以下是该类的一些属性和方法:

Public Sub New(ByVal path As String)
从文件 path 打开一个流。如果该文件不存在,则抛出异常
Overrides Public Sub Close()
关闭该流
Overrides Public Function ReadLine() As String
从已打开的流中读取一行
Overrides Public Function ReadToEnd() As String
从当前位置读取流的剩余部分

以下是一个示例:


' 选项
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 用于向文件写入数据。以下是该类的一些属性和方法:

Public Sub New(ByVal path As String)
从文件 path 打开一个写入流。如果无法创建该文件,则会抛出异常
Public Overridable Property AutoFlush
As Boolean
若为真,则写入流时不经过缓冲区;否则写入流并非即时进行:首先写入缓冲区,待缓冲区满后再写入流。默认使用缓冲模式。该模式适用于文件流,但通常不适用于网络流。
Public Overridable Property NewLine
As String
用于设置或查询方法 WriteLine 所使用的换行符
Overrides Public Sub Close()
关闭数据流
Overloads Public Overridable Sub
WriteLine(ByVal value As String)
在写入流中写入一行
Overrides Public Sub Flush()
将缓冲区写入流

请看以下示例:


' 选项
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 类支持正则表达式。正则表达式可用于验证字符串的格式。例如,我们可以验证表示日期的字符串是否符合 dd/mm/yy 格式。为此,我们需要使用一个模式,并将字符串与该模式进行比较。因此,在此示例中,j、m 和 a 必须是数字。 因此,有效的日期格式模式为“\d\d/\d\d/\d\d”,其中符号 \d 表示数字。模式中可使用的符号如下(微软文档):

 
描述
\
将后续字符标记为特殊字符或字面字符。例如,“n”表示字符“n”。“\n”表示换行符。字符序列“\\”表示“\”,而“\("表示“(”。
^
表示输入的开头。
$
表示输入结束。
*
表示前一个字符零次或多次出现。因此,“zo*”表示“z”或“zoo”。
+
匹配前一个字符一次或多次。因此,“zo+”匹配“zoo”,但不匹配“z”。
?
匹配前一个字符零次或一次。例如,“a?ve?”匹配“lever”中的“ve”。
.
匹配除换行符以外的任何单个字符。

(modèle)
搜索 modèle 并记录匹配结果。可以通过 Item [0]...[n] 从获得的 Matches 集合中提取匹配的子字符串。 若要查找包含括号 ( ) 内的字符的匹配项,请使用 "\(" 或 "\)"。

x|y
匹配 xy。例如,“z|foot”匹配“z”或“foot”。“(z|f)oo”匹配“zoo”或“foo”。

{n}
n 是一个非负整数。精确匹配 n 倍的该字符。例如,“o{2}”不匹配“Bob”中的“o”,而是匹配“fooooot”中的前两个“o”。

{n,}
n 是一个非负整数。匹配该字符至少 n 次。 例如,“o{2,}”不匹配“Bob”中的“o”,而是匹配“fooooot”中的所有“o”。“o{1,}”等同于“o+”,而“o{0,}”等同于“o*”。

{n,m}
m n 是非负整数。 表示该字符出现次数不少于 n 次,且不超过 m 次。例如,“o{1,3}”匹配“foooooot”中的前三个“o”,而“o{0,1}”等同于“o?”。

[xyz]
字符集。匹配所列出的任意一个字符。例如,“[abc]”匹配“plat”中的“a”。

[^xyz]
否定字符集。匹配所有未列出的字符。例如,“[^abc]”匹配“plat”中的“p”。

[a-z]
字符范围。匹配指定字符序列中的任何字符。例如,“[a-z]”匹配“a”到“z”之间的所有小写字母。

[^m-z]
负字符集。匹配指定字符集中的所有非字符。例如,“[^m-z]”匹配“m”和“z”之间的所有非字符。
\b
匹配表示单词的边界,即单词与空格之间的位置。例如,“er\b”匹配“lever”中的“er”,但不匹配“verbe”中的“er”。
\B
对应不代表单词的边界。“en*t\B”对应“bien entendu”中的“ent”。
\d
匹配代表数字的字符。等同于 [0-9]。
\D
对应于不代表数字的字符。等同于 [^0-9]。
\f
对应于换行符。
\n
对应换行符。
\r
对应回车符。
\s
对应所有空白字符,包括空格、制表符、换行符等。等同于“[ \f\n\r\t\v]”。
\S
匹配所有非空白字符。等同于“[^ \f\n\r\t\v]”。
\t
匹配一个制表符。
\v
对应一个垂直制表符。
\w
对应于任何代表单词且包含下划线的字符。等同于“[A-Za-z0-9_]”。
\W
对应于任何不代表单词的字符。等同于“[^A-Za-z0-9_]”。

\num
对应于 num,其中 num 是一个正整数。指代存储的映射关系。例如,"(.)\1" 对应于两个连续的相同字符。

\n
对应于 n,其中 n 是一个八进制转义值。八进制转义值必须包含 1、2 或 3 个数字。例如,“\11”和“\011”都对应于一个制表符。 "\0011" 等同于 "\001" & "1"。八进制转义值不得超过 256。如果超过,则表达式中仅考虑前两位数字。允许在正则表达式中使用 ASCII 代码。

\xn
对应于 n,其中 n 是一个十六进制转义值。 十六进制转义值必须包含两个数字。例如,“\x41”对应“A”。“\x041”等同于“\x04”和“1”。允许在正则表达式中使用代码 ASCII。

模板中的一个元素可以出现一次或多次。以下是关于符号 \d(代表 1 个数字)的一些示例:

模板
含义
\d
一个数字
\d?
0 或 1 位数字
\d*
0个或多个数字
\d+
1个或多个数字
\d{2}
2个数字
\d{3,}
至少3位数字
\d{5,7}
5至7位数字

现在设想一个能够描述字符串预期格式的模型:

目标字符串
模式
une date au format jj/mm/aa
\d{2}/\d{2}/\d{2}
une heure au format hh:mm:ss
\d{2}:\d{2}:\d{2}
un nombre entier non signé
\d+
un suite d'espaces éventuellement vide
\s*
un nombre entier non signé qui peut être précédé ou suivi d'espaces
\s*\d+\s*
un nombre entier qui peut être signé et précédé ou suivi d'espaces
\s*[+|-]?\s*\d+\s*
un nombre réel non signé qui peut être précédé ou suivi d'espaces
\s*\d+(.\d*)?\s*
un nombre réel qui peut être signé et précédé ou suivi d'espaces
\s*[+|]?\s*\d+(.\d*)?\s*
une chaîne contenant le mot juste
\bjuste\b
  

可以指定在字符串中的哪个位置搜索该模式:

模式
含义
^modèle
该模板位于字符串开头
modèle$
模板结束字符串
^modèle$
模板开始并结束字符串
modèle
从字符串开头开始,在整个字符串中搜索该模式。
要搜索的字符串
模式
une chaîne se terminant par un point d'exclamation
!$
une chaîne se terminant par un point
\.$
une chaîne commençant par la séquence //
^//
une chaîne ne comportant qu'un mot éventuellement suivi ou précédé d'espaces
^\s*\w+\s*$
une chaîne ne comportant deux mot éventuellement suivis ou précédés d'espaces
^\s*\w+\s*\w+\s*$
une chaîne contenant le mot secret
\bsecret\b

模式的子集可以被“提取”。因此,我们不仅可以验证一个字符串是否符合特定模式,还可以从该字符串中提取那些用圆括号括起的、与模式子集对应的元素。 例如,若要分析包含日期格式 dd/mm/yy 的字符串,并提取其中的 dd、mm、yy 元素,可使用正则表达式 (\d\d)/(\d\d)/(\d\d)。

4.9.1. 验证字符串是否符合给定模式

Regex 类型的对象构建方式如下:

Public Sub New(ByVal pattern As String)

构造函数会根据作为参数传递的模板(pattern)创建一个“正则表达式”对象。一旦构建了正则表达式模板,即可使用方法 IsMatch 将其与字符串进行比较:

Overloads Public Function IsMatch(ByVal input As String) As Boolean

如果输入字符串与正则表达式模式匹配,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 方法

Overloads Public Function Matches(ByVal input As String) As MatchCollection

返回字符串 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. 提取模式的子集

可以“提取”模式的子集。因此,我们不仅可以验证字符串是否符合特定模式,还可以从该字符串中提取模式中用圆括号括起的子集对应的元素。 例如,若要解析包含日期格式 dd/mm/yy 的字符串,并提取其中的 dd、mm、yy 元素,可使用正则表达式 (\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 通过方法 Match 与模板 regex3 进行比较。该方法返回一个已介绍过的 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 中已经遇到过这个方法:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()

字符串被视为由数组 [separator] 中包含的字符分隔的一系列字段。结果是这些字段的数组。

此处字符串的字段分隔符是 separator 数组中的某个字符。Regex 类中的 Split 方法允许我们根据模式来指定分隔符:

Overloads Public Function Split(ByVal input As String) As String()

字符串 [input] 被分解为各个字段,这些字段由一个分隔符分隔,该分隔符对应于当前对象 Regex 的模板。 例如,假设我们在一个文本文件中拥有形式为字段1、字段2、...、字段n的行。字段之间以逗号分隔,但逗号前后可能带有空格。 此时,类 string 中的方法 Split 并不适用。方法 RegEx 则提供了解决方案。若 line 是已读取的行,则可通过以下方式获取字段:

dim champs() as string=new Regex("s*,\s*").Split(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

BinaryReaderBinaryWriter 用于读写二进制文件。考虑以下应用场景。我们希望编写一个程序,其调用方式如下:

// pg文本二进制语法
// 读取文本文件(文本)并将内容存储到
// 二进制文件中
// 该文本文件包含以下格式的行:姓名:年龄
// 我们将这些数据存储在字符串和整数结构中

该文本文件的内容如下:

paul : 10
helene : 15
jacques : 11
sylvain : 12

程序如下:


' 选项
Option Strict On
Option Explicit On 

' 命名空间
Imports System
Imports System.Text.RegularExpressions
Imports System.IO

' BinaryWriter()

Module bw1
    ' 语法 pg 文本 bin
    ' 读取文本文件(文本)并将内容存储在
    ' 二进制文件中
    ' 该文本文件包含形式为“姓名:年龄”的行
    ' 将其存储在字符串、整数结构中

    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 相关的操作:

  • 操作

            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,用于写入不同类型的简单数据

  • 关闭数据流的操作
        output.Close()

以下程序将提供前一次执行的结果。该程序同样接受两个参数:

    ' pg bin 文本语法
    ' 读取二进制文件 bin 并将内容保存到文本文件(文本)中
    ' 二进制文件具有字符串、整数结构
    ' 文本文件中的行格式为 姓名 : 年龄

因此,我们进行逆向操作。读取二进制文件以生成文本文件。如果生成的文本文件与原始文件完全一致,则说明文本→二进制→文本的转换过程已成功完成。代码如下:


' 选项
Option Strict On
Option Explicit On 

' 命名空间
Imports System
Imports System.Text.RegularExpressions
Imports System.IO

Module br1
    ' pg二进制文本语法
    ' 读取二进制文件 bin,并将内容保存到文本文件(文本)中
    ' 二进制文件具有字符串、整数结构
    ' 文本文件中的行格式为 姓名 : 年龄

    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,表示对文件的读取访问
  • 读取操作
                nom = dataIn.ReadString()
                age = dataIn.ReadInt32()

BinaryReader 提供了多种方法 ReadXX 用于读取不同类型的简单数据

  • 关闭流的操作
        dataIn.Close()

如果按顺序执行这两个程序,将 personnes.txt 转换为 personnes.bin,然后将 personnes.bin 转换为 personnes.txt2,结果如下:

dos>more personnes.txt
paul : 10
helene : 15
jacques : 11
sylvain : 12

dos>more personnes.txt2
paul:10
helene:15
jacques:11
sylvain:12

dos>dir
29/04/2002  18:19                   54 personnes.txt
29/04/2002  18:19                   44 personnes.bin
29/04/2002  18:20                   44 personnes.txt2