4. Classes .NET de uso comum
Apresentamos aqui algumas classes da plataforma .NET que são de interesse, mesmo para um iniciante. Mostramos, em primeiro lugar, como obter informações sobre as centenas de classes disponíveis.
4.1. Buscar ajuda com SDK.NET
4.1.1. wincv
Se tiver sido instalado apenas o SDK e não o Visual Studio.NET, será possível utilizar o programa wincv.exe, normalmente localizado na estrutura de diretórios do SDK, por exemplo, C:\Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1. Ao executar esse utilitário, é exibida a seguinte interface:
![]() |
Digita-se em (1) o nome da classe desejada. Isso exibe em (2) vários temas possíveis. Escolhe-se o mais adequado e obtém-se o resultado em (3), neste caso, a classe HashTable. Esse método é adequado se soubermos o nome da classe que estamos procurando. Se quisermos explorar a lista de possibilidades oferecidas pela plataforma .NET, pode-se usar o arquivo HTML StartHere.htm, que também está localizado diretamente na pasta de instalação do SSK.Net, por exemplo, C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

O link .NET Framework SDK Documentação é o que deve ser acessado para obter uma visão geral das classes .NET:

Nesse link, seguiremos o link [Bibliothèque de classes]. Lá, encontramos a lista de todas as classes de .NET:

Vamos seguir, por exemplo, o link System.Collections. Esse espaço de nomes reúne diversas classes que implementam coleções, entre as quais a classe HashTable:

Vamos seguir o link HashTable abaixo:

Chegamos à seguinte página:

Observe, abaixo, a posição do cursor. Ele está apontando para um link que permite especificar a linguagem desejada, neste caso, Visual Basic.
Lá encontramos o protótipo da classe, bem como exemplos de uso. Vamos acessar o link [Hashtable, membres] abaixo:

Obtemos a descrição completa da classe:

Esse método é o melhor para explorar o SDK e suas classes. A ferramenta WinCV é útil quando já se tem algum conhecimento sobre a classe, mas se esqueceu de alguns de seus membros. O WinCV permite, então, localizar rapidamente a classe e seus membros.
4.2. Buscar ajuda sobre as classes com o VS.NET
Apresentamos aqui algumas orientações para encontrar ajuda com o Visual Studio.NET
4.2.1. Opção Ajuda
Selecione a opção [?] no menu.

Aparece a seguinte janela:

Na lista suspensa, é possível selecionar um filtro de ajuda. Aqui, vamos escolher o filtro [Visual Basic].

Há duas ajudas úteis:
- a ajuda sobre a própria linguagem VB.NET (sintaxe)
- a ajuda sobre os classes.NET que podem ser utilizados pela linguagem VB.NET
A ajuda sobre a linguagem VB.NET pode ser acessada por meio de [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic]:

É exibida a seguinte página de ajuda:

A partir daí, as diferentes subseções permitem que obtenhamos ajuda sobre diversos temas do VB.NET. Preste atenção aos tutoriais do VB.NET:

Para acessar as diferentes classes da plataforma .NET, selecione a ajuda [Visual Studio.NET/.NET Framework].

Vamos nos concentrar, em particular, na seção [Référence/Bibliothèque de classes]:

Suponhamos que estejamos interessados na classe [ArrayList]. Ela está localizada no espaço de nomes [System.Collections]. É importante saber disso; caso contrário, é preferível utilizar o método de pesquisa descrito a seguir. Obtemos a seguinte ajuda:

O link [ArrayList, classe] fornece uma visão geral da classe:

Esse tipo de página existe para todas as classes. Ela apresenta um resumo da classe com exemplos. Para obter uma descrição dos membros da classe, acesse o link [ArrayList, membres]:

4.2.2. Ajuda/Índice

A opção [Aide/index] permite buscar uma ajuda mais específica do que a anterior. Basta digitar a palavra-chave procurada:

A vantagem desse método em relação ao anterior é que não é necessário saber onde se encontra o que se procura no sistema de ajuda. Esse é provavelmente o método preferível quando se faz uma pesquisa direcionada, já que o outro método é mais adequado para explorar tudo o que a ajuda oferece.
4.3. A classe String
A classe String possui diversas propriedades e métodos. Aqui estão alguns deles:
número de caracteres da string | |
propriedade indexada por padrão. [String].Chars(i) é o caractere nº i da string | |
retorna verdadeiro se a string terminar com o valor | |
retorna verdadeiro se a string começar com o valor | |
retorna verdadeiro se a string for igual a value | |
retorna a primeira posição da string na string value — a busca começa a partir do caractere nº 0 | |
retorna a primeira posição na string do valor - a busca começa a partir do caractere nº startIndex | |
método de classe — retorna uma sequência de caracteres, resultado da concatenação dos valores da matriz value com o separador separator | |
retorna uma cópia da string atual, na qual o caractere oldChar foi substituído pelo caractere newChar | |
a string é considerada como uma sequência de campos separados pelos caracteres presentes na tabela separator. O resultado é a tabela desses campos | |
subcadeia da cadeia atual que começa na posição startIndex e possui length caracteres | |
converte a cadeia atual em letras minúsculas | |
converte a string atual em maiúsculas | |
remove os espaços no início e no final da string atual |
Uma cadeia C pode ser considerada como uma matriz de caracteres. Assim,
- C.Chars(i) é o caractere i de C
- C.Length é o número de caracteres de C
Consideremos o seguinte exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
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
' exibe
Sub affiche(ByVal msg As [String])
' exibe mensagem
Console.Out.WriteLine(msg)
End Sub
End Module
A execução produz os seguintes resultados:
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]
Vamos considerar um novo exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Module string2
Sub Main()
' a linha a ser analisada
Dim ligne As String = "un:deux::trois:"
' separadores de campos
Dim séparateurs() As Char = {":"c}
' divisão
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
' junção
Console.Out.WriteLine(("join=[" + System.String.Join(":", champs) + "]"))
End Sub
End Module
e os resultados da execução:
O método Split da classe String permite colocar os campos de uma sequência de caracteres em uma matriz. A definição do método utilizado aqui é a seguinte:
matriz de caracteres. Esses caracteres representam os caracteres utilizados para separar os campos da sequência de caracteres. Assim, se a sequência for [champ1, champ2, champ3], poderá-se utilizar separator=new char() {","c}. Se o separador for uma sequência de espaços, utilizar-se-á separator=nothing. | |
matriz de cadeias de caracteres em que cada elemento é um campo da cadeia. |
O método Join é um método estático da classe String:
matriz de cadeias de caracteres | |
uma sequência de caracteres que servirá como separador de campos | |
uma sequência de caracteres formada pela concatenação dos elementos da matriz value, separados pela sequência separator. |
4.4. A classe Array
A classe Array implementa um array. Utilizaremos, em nosso exemplo, as seguintes propriedades e métodos:
propriedade — número de elementos da matriz | |
método de classe — retorna a posição de value na matriz ordenada array — pesquisa a partir da posição index e com length elementos | |
método de classe — copia os elementos de length de sourceArray para destinationArray — destinationArray é criado para a ocasião | |
método de classe — ordena a matriz array — esta deve conter um tipo de dados com uma função de ordenação padrão (cadeias de caracteres, números). |
O programa a seguir ilustra o uso da classe Array:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Module test
Sub Main()
' leitura dos elementos de uma matriz digitados pelo teclado
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é
' pergunta
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' leitura da resposta
réponse = Console.ReadLine().Trim()
' fim da entrada se a string estiver vazia
If réponse.Equals("") Then
Exit While
End If
' verificação da entrada
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' se não houver erro
If Not erreur Then
' nova tabela para receber o novo elemento
éléments2 = New Double(i) {}
' cópia da matriz antiga para a nova matriz
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' a nova tabela passa a ser a tabela antiga
éléments1 = éléments2
' não há mais necessidade da nova tabela
éléments2 = Nothing
' inserção de um novo elemento
éléments1(i) = élément
' mais um elemento na tabela
i += 1
End If
End While
' exibição da tabela sem ordenação
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
' classificação da tabela
System.Array.Sort(éléments1)
' exibição da tabela ordenada
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
' Pesquisa
While Not terminé
' pergunta
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' Leitura e verificação da resposta
réponse = Console.ReadLine().Trim()
' Concluído?
If réponse.Equals("") Then
Exit While
End If
' verificação
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' se não houver erro
If Not erreur Then
' procura-se o elemento na tabela ordenada
i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
' Exibição da resposta
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
Os resultados na tela são os seguintes:
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) :
A primeira parte do programa cria uma matriz a partir de dados numéricos digitados pelo teclado. O tamanho da matriz não pode ser definido antecipadamente, pois não se sabe quantos elementos o usuário irá digitar. Trabalha-se, portanto, com duas matrizes: éléments1 e éléments2.
' nova matriz para receber o novo elemento
éléments2 = New Double(i) {}
' cópia da tabela antiga para a nova tabela
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' a nova tabela passa a ser a tabela antiga
éléments1 = éléments2
' não há mais necessidade da nova tabela
éléments2 = Nothing
' inserção de um novo elemento
éléments1(i) = élément
' mais um elemento na tabela
i += 1
A matriz éléments1 contém os valores atualmente inseridos. Quando o usuário adiciona um novo valor, cria-se uma matriz éléments2 com um elemento a mais do que éléments1, copia-se o conteúdo de éléments1 para éléments2 (Array.Copy), faz-se com que éléments1 “aponte” para éléments2 e, por fim, adiciona-se o novo elemento a éléments1. Trata-se de um processo complexo que pode ser simplificado se, em vez de usar uma matriz de tamanho fixo (Array), utilizarmos uma matriz de tamanho variável (ArrayList).
A matriz é classificada com o método Array.Sort. Esse método pode ser chamado com diferentes parâmetros que especificam as regras de classificação. Sem parâmetros, é realizada, por padrão, uma classificação em ordem crescente. Por fim, o método Array.BinarySearch permite procurar um elemento em uma matriz classificada.
4.5. A classe ArrayList
A classe ArrayList permite implementar tabelas de tamanho variável durante a execução do programa, o que não é possível com a classe Array anterior. Aqui estão algumas das propriedades e métodos mais comuns:
cria uma lista vazia | |
número de elementos da coleção | |
adiciona o objeto value ao final da coleção | |
apaga a lista | |
índice do objeto value na lista ou -1 caso ele não exista | |
O mesmo, mas buscando a partir do elemento nº startIndex | |
O mesmo, mas retorna o índice da última ocorrência de “value” na lista | |
O mesmo, mas buscando a partir do elemento nº startIndex | |
remove o objeto obj, caso ele exista na lista | |
remove o elemento index da lista | |
retorna a posição do objeto `value` na lista ou -1 caso ele não esteja presente. A lista deve estar ordenada | |
ordena a lista. Ela deve conter objetos com uma relação de ordem predefinida (cadeias de caracteres, números) | |
ordena a lista de acordo com a relação de ordem estabelecida pela função comparar |
Vamos retomar o exemplo tratado com objetos do tipo Array e processá-lo com objetos do tipo ArrayList:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Module test
Sub Main()
' leitura dos elementos de uma tabela digitados pelo teclado
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é
' pergunta
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' leitura da resposta
réponse = Console.ReadLine().Trim()
' fim da entrada se a string estiver vazia
If réponse.Equals("") Then
Exit While
End If
' verificação da entrada
Try
élément = Double.Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' se não houver erro
If Not erreur Then
' mais um elemento na tabela
éléments.Add(élément)
End If
End While
' exibição da tabela não ordenada
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()
' exibição da tabela ordenada
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
' Pesquisa
While Not terminé
' pergunta
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' Leitura e verificação da resposta
réponse = Console.ReadLine().Trim()
' terminou?
If réponse.Equals("") Then
Exit While
End If
' verificação
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' se não houver erro
If Not erreur Then
' procura-se o elemento na tabela ordenada
i = éléments.BinarySearch(élément)
' Exibição da resposta
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
Os resultados da execução são os seguintes:
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. A classe Hashtable
A classe Hashtable permite implementar um dicionário. Pode-se considerar um dicionário como uma tabela com duas colunas:
![]() |
As chaves são únicas, c.a.d, ou seja, não pode haver duas chaves idênticas. Os principais métodos e propriedades da classe Hashtable são os seguintes:
cria um dicionário vazio | |
adiciona uma linha (chave, valor) ao dicionário, em que chave e valor são referências a objetos. | |
remove do dicionário a linha com chave=key | |
esvazia o dicionário | |
retorna verdadeiro (true) se a chave key pertencer ao dicionário. | |
retorna verdadeiro (true) se o valor value pertencer ao dicionário. | |
propriedade: número de elementos do dicionário (chave, valor) | |
propriedade: coleção das chaves do dicionário | |
propriedade: coleção de valores do dicionário | |
propriedade indexada: permite consultar ou definir o valor associado a uma chave |
Consideremos o seguinte programa de exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
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}
' preenchimento do dicionário
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
' número de elementos no dicionário
Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
' lista de chaves
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
' lista de valores
Console.Out.WriteLine("[Liste des valeurs]")
Dim valeurs As IEnumerator = dico.Values.GetEnumerator()
While valeurs.MoveNext()
Console.Out.WriteLine(valeurs.Current)
End While
' lista de chaves e valores
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
' a chave “paul” é excluída
Console.Out.WriteLine("[Suppression d'une clé]")
dico.Remove("paul")
' lista de chaves e valores
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
' pesquisa no dicionário
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
' próxima pesquisa
Console.Out.Write("Nom recherché (rien pour arrêter) : ")
nomCherché = Console.ReadLine().Trim()
End While
End Sub
End Module
Os resultados da execução são os seguintes:
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) :
O programa também utiliza um objeto IEnumerator para percorrer as coleções de chaves e valores do dicionário do tipo ICollection (veja acima as propriedades Keys e Values). Uma coleção é um conjunto de objetos que pode ser percorrido. A interface ICollection é definida da seguinte forma:

A propriedade Count permite saber o número de elementos da coleção. A interface ICollection deriva da interface IEnumerable:

Essa interface possui apenas um método, GetEnumerator, que nos permite obter um objeto do tipo IEnumerator:

O método GetEnumerator() de uma coleção ICollection permite percorrer a coleção com os seguintes métodos:
posiciona no próximo elemento da coleção. Retorna verdadeiro (true) se esse elemento existir, falso (false) caso contrário. O primeiro MoveNext posiciona no primeiro elemento. O elemento “atual” da coleção fica então disponível na propriedade Current do enumerador | |
propriedade: elemento atual da coleção | |
reposiciona o enumerador no início da coleção, c.a.d, antes do primeiro elemento. |
A estrutura de iteração sobre os elementos de uma coleção (ICollection) em C é, portanto, a seguinte:
' definir a coleção
dim C as ICollection C=...
' obter um enumerador dessa coleção
dim itérateur as IEnumerator=C.GetEnumerator();
' percorrer a coleção com esse enumerador
while(itérateur.MoveNext())
' temos um elemento atual
' processar itérateur.Current
end while
4.7. A classe StreamReader
A classe StreamReader permite ler o conteúdo de um arquivo. Aqui estão algumas de suas propriedades e métodos:
abre um fluxo a partir do arquivo path. É lançada uma exceção se o arquivo não existir | |
fecha o fluxo | |
lê uma linha do fluxo aberto | |
lê o restante do fluxo a partir da posição atual |
Veja um exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Imports System.IO
Module test
Sub Main()
Dim ligne As String = Nothing
Dim fluxInfos As StreamReader = Nothing
' leitura do conteúdo do arquivo
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
e seus resultados de execução:
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. A classe StreamWriter
A classe StreamWriter permite gravar em um arquivo. Aqui estão algumas de suas propriedades e métodos:
abre um fluxo de gravação a partir do arquivo path. Uma exceção é lançada se ele não puder ser criado | |
se for igual a verdadeiro, a gravação no fluxo não passa por um buffer; caso contrário, a gravação no fluxo não é imediata: primeiro ocorre a gravação em um buffer e, em seguida, no fluxo quando o buffer estiver cheio. Por padrão, é utilizado o modo com buffer. Ele é adequado para fluxos de arquivo, mas geralmente não para fluxos de rede. | |
para definir ou verificar o caractere de fim de linha a ser usado pelo método WriteLine | |
fecha o fluxo | |
grava uma linha no fluxo de gravação | |
grava o buffer no fluxo |
Consideremos o seguinte exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
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
' criação do arquivo de texto
fluxInfos = New StreamWriter("infos.txt")
' leitura da linha digitada no teclado
Console.Out.Write("ligne (rien pour arrêter) : ")
ligne = Console.In.ReadLine().Trim()
' loop enquanto a linha digitada não estiver vazia
While ligne <> ""
' gravação da linha no arquivo de texto
fluxInfos.WriteLine(ligne)
' leitura de uma nova linha digitada no teclado
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
' fechamento do arquivo
Try
fluxInfos.Close()
Catch
End Try
End Try
End Sub
End Module
e os resultados da execução:
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. A classe Regex
A classe Regex permite o uso de expressões regulares. Elas permitem verificar o formato de uma sequência de caracteres. Assim, é possível verificar se uma sequência que representa uma data está, de fato, no formato dd/mm/aa. Para isso, utiliza-se um modelo e compara-se a sequência com esse modelo. Portanto, neste exemplo, j, m e a devem ser números. O modelo de um formato de data válido é, portanto, “\d\d/\d\d/\d\d”, onde o símbolo \d representa um algarismo. Os símbolos que podem ser utilizados em um modelo são os seguintes (documentação da Microsoft):
Descrição | |
Marca o caractere seguinte como especial ou literal. Por exemplo, “n” corresponde ao caractere “n”. “\n” corresponde a um caractere de nova linha. A sequência “\\” corresponde a “\”, enquanto “\(" corresponde a “(”. | |
Corresponde ao início da entrada. | |
Corresponde ao fim da entrada. | |
Corresponde ao caractere anterior zero ou mais vezes. Assim, “zo*” corresponde a “z” ou a “zoo”. | |
Corresponde ao caractere anterior uma ou mais vezes. Assim, “zo+” corresponde a “zoo”, mas não a “z”. | |
Corresponde ao caractere anterior zero ou uma vez. Por exemplo, “a?ve?” corresponde a “ve” em “lever”. | |
Corresponde a qualquer caractere único, exceto o caractere de nova linha. | |
| Pesquisa o modèle e armazena a correspondência. A subcadeia correspondente pode ser extraída da coleção Matches obtida, por meio do Item [0]...[n]. Para encontrar correspondências com caracteres entre parênteses ( ), use "\(" ou "\)". |
| Corresponde a x ou a y. Por exemplo, “z|foot” corresponde a “z” ou a “foot”. “(z|f)oo” corresponde a “zoo” ou a “foo”. |
| n é um número inteiro não negativo. Corresponde exatamente a n vezes o caractere. Por exemplo, “o{2}” não corresponde a “o” em “Bob”, mas aos dois primeiros “o” em “fooooot”. |
| n é um número inteiro não negativo. Corresponde a pelo menos n vezes o caractere. Por exemplo, “o{2,}” não corresponde ao “o” em “Bob”, mas a todos os “o” em “fooooot”. “o{1,}” equivale a “o+” e “o{0,}” equivale a “o*”. |
| m e n são números inteiros não negativos. Corresponde a pelo menos n e, no máximo, m vezes o caractere. Por exemplo, “o{1,3}” corresponde aos três primeiros “o” em “foooooot” e “o{0,1}” equivale a “o?”. |
| Conjunto de caracteres. Corresponde a um dos caracteres indicados. Por exemplo, “[abc]” corresponde a “a” em “plat”. |
| Conjunto de caracteres negativo. Corresponde a qualquer caractere não indicado. Por exemplo, “[^abc]” corresponde a “p” em “plat”. |
| Intervalo de caracteres. Corresponde a qualquer caractere na série especificada. Por exemplo, “[a-z]” corresponde a qualquer letra minúscula entre “a” e “z”. |
| Intervalo de caracteres negativo. Corresponde a qualquer caractere que não esteja na série especificada. Por exemplo, “[^m-z]” corresponde a qualquer caractere que não esteja entre “m” e “z”. |
Corresponde a um limite que representa uma palavra; em outras palavras, à posição entre uma palavra e um espaço. Por exemplo, “er\b” corresponde a “er” em “lever”, mas não a “er” em “verbe”. | |
Corresponde a um limite que não representa uma palavra. “en*t\B” corresponde a “ent” em “bien entendu”. | |
Corresponde a um caractere que representa um algarismo. É equivalente a [0-9]. | |
Corresponde a um caractere que não representa um algarismo. É equivalente a [^0-9]. | |
Corresponde a um caractere de quebra de página. | |
Corresponde a um caractere de nova linha. | |
Corresponde a um caractere de retorno de carro. | |
Corresponde a qualquer espaço em branco, incluindo espaço, tabulação, quebra de página etc. É equivalente a “[ \f\n\r\t\v]”. | |
Corresponde a qualquer caractere de espaço não em branco. É equivalente a “[^ \f\n\r\t\v]”. | |
Corresponde a um caractere de tabulação. | |
Corresponde a um caractere de tabulação vertical. | |
Corresponde a qualquer caractere que represente uma palavra e inclua um sublinhado. É equivalente a “[A-Za-z0-9_]”. | |
Corresponde a qualquer caractere que não represente uma palavra. É equivalente a “[^A-Za-z0-9_]”. | |
| Corresponde a num, onde num é um número inteiro positivo. Refere-se às correspondências armazenadas. Por exemplo, “(.)\1” corresponde a dois caracteres idênticos consecutivos. |
| Corresponde a n, onde n é um valor de escape octal. Os valores de escape octais devem conter 1, 2 ou 3 dígitos. Por exemplo, “\11” e “\011” correspondem ambos a um caractere de tabulação. "\0011" equivale a "\001" e "1". Os valores de escape octais não devem exceder 256. Se isso ocorrer, apenas os dois primeiros dígitos serão considerados na expressão. Permite usar os códigos ASCII em expressões regulares. |
| Corresponde a n, onde n é um valor de escape hexadecimal. Os valores de escape hexadecimais devem conter obrigatoriamente dois dígitos. Por exemplo, “\x41” corresponde a “A”. “\x041” equivale a “\x04” e “1”. Permite usar os códigos ASCII em expressões regulares. |
Um elemento em um modelo pode estar presente uma ou mais vezes. Vejamos alguns exemplos relacionados ao símbolo \d, que representa um dígito:
modelo | significado |
um número | |
0 ou 1 dígito | |
0 ou mais dígitos | |
1 ou mais dígitos | |
2 dígitos | |
pelo menos 3 dígitos | |
entre 5 e 7 dígitos |
Imaginemos agora o modelo capaz de descrever o formato esperado para uma sequência de caracteres:
sequência procurada | modelo |
\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* | |
\bjusto\b | |
É possível especificar onde procurar o padrão na sequência:
padrão | significado |
o modelo inicia a sequência | |
o modelo termina a sequência | |
o modelo inicia e encerra a sequência | |
o padrão é procurado em toda a sequência, começando pelo início dela. |
cadeia procurada | padrão |
!$ | |
\.$ | |
^// | |
^\s*\w+\s*$ | |
^\s*\w+\s*\w+\s*$ | |
\bsecret\b |
Os subconjuntos de um padrão podem ser “recuperados”. Assim, não só é possível verificar se uma sequência corresponde a um padrão específico, como também é possível recuperar nessa sequência os elementos correspondentes aos subconjuntos do padrão que foram colocados entre parênteses. Assim, se analisarmos uma sequência de caracteres contendo uma data dd/mm/aa e quisermos, além disso, extrair os elementos dd, mm e aa dessa data, utilizaremos o modelo (\d\d)/(\d\d)/(\d\d).
4.9.1. Verificar se uma sequência corresponde a um determinado modelo
Um objeto do tipo Regex é construído da seguinte maneira:
O construtor cria um objeto “expressão regular” a partir de um padrão passado como parâmetro (pattern). Uma vez construída a expressão regular modelo, é possível compará-la a cadeias de caracteres com o método IsMatch:
IsMatch retorna verdadeiro se a string de entrada corresponder ao padrão da expressão regular. Veja um exemplo:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex1
Sub Main()
' uma expressão regular modelo
Dim modèle1 As String = "^\s*\d+\s*$"
Dim regex1 As New Regex(modèle1)
' comparar uma instância com o modelo
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
' exibe
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
e os resultados da execução:
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. Encontrar todos os elementos de uma sequência que correspondam a um padrão
O método Matches
retorna uma coleção de elementos da string input que correspondem ao padrão, conforme mostrado no exemplo a seguir:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' várias ocorrências do modelo na instância
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
'exibe
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
A classe MatchCollection possui uma propriedade Count, que representa o número de elementos da coleção. Se résultats é um objeto MatchCollection, résultats(i) é o elemento i dessa coleção e é do tipo Match. Em nosso exemplo, résultats é o conjunto de elementos da cadeia exemplaire3 correspondentes ao modelo modèle2, e résultats(i) é um desses elementos. A classe Match possui duas propriedades que nos interessam aqui:
- Value: o valor do objeto Match, ou seja, o elemento correspondente ao modelo
- Index: a posição em que o elemento foi encontrado na sequência explorada
Os resultados da execução do programa anterior:
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. Recuperar partes de um modelo
Subconjuntos de um modelo podem ser “recuperados”. Assim, não só é possível verificar se uma sequência corresponde a um modelo específico, como também é possível recuperar nessa sequência os elementos correspondentes aos subconjuntos do modelo que foram colocados entre parênteses. Assim, se analisarmos uma sequência de caracteres contendo uma data dd/mm/aa e quisermos, além disso, extrair os elementos dd, mm e aa dessa data, utilizaremos o modelo (\d\d)/(\d\d)/(\d\d). Vejamos o exemplo a seguir:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' captura de elementos no modelo
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"
' verificação do modelo
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' a cópia corresponde ao modelo
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' exibição dos grupos
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
' o exemplar não corresponde ao modelo
affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
End If
End Sub
'exibe
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
A execução deste programa produz os seguintes resultados:
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
A novidade está na seguinte parte do código:
' verificação do modelo
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' o exemplar corresponde ao modelo
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' exibindo os grupos
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
A string exemplaire4 é comparada ao modelo regex3 por meio do método Match. Esse método retorna um objeto Match já apresentado. Utilizamos aqui duas novas propriedades dessa classe:
- Success: indica se houve correspondência
- Groups: coleção na qual
- Groups[0] corresponde à parte da string que corresponde ao modelo
- Groups[i] (i>=1) corresponde ao grupo de parênteses nº i
Se o resultado for do tipo Match, résultats.Groups é do tipo GroupCollection e résultats.Groups[i] é do tipo Group. A classe Group possui duas propriedades que utilizamos aqui:
- Value: o valor do objeto Group, que é o elemento correspondente ao conteúdo de um parêntese
- Index: a posição em que o elemento foi encontrado na string analisada
4.9.4. Um programa de treino
Encontrar a expressão regular que nos permite verificar se uma cadeia corresponde de fato a um determinado modelo é, às vezes, um verdadeiro desafio. O programa a seguir permite praticar. Ele solicita um modelo e uma cadeia e, em seguida, indica se a cadeia corresponde ou não ao modelo.
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic
Module regex4
Sub Main()
' uma expressão regular modelo
Dim modèle, chaine As String
Dim regex As Regex = Nothing
Dim résultats As MatchCollection
' solicita-se ao usuário os modelos e exemplares a serem comparados com este
Dim terminé1 As Boolean = False
Do While Not terminé1
Dim erreur As Boolean = True
Do While Not terminé1 And erreur
' solicita-se o modelo
Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
modèle = Console.In.ReadLine()
' Concluído?
If modèle.Trim().ToLower() = "fin" Then
terminé1 = True
Else
' cria-se a expressão regular
Try
regex = New Regex(modèle)
erreur = False
Catch ex As Exception
Console.Error.WriteLine(("Erreur : " + ex.Message))
End Try
End If
Loop
' Concluído?
If terminé1 Then Exit Sub
' solicita-se ao usuário os exemplares a serem comparados com o modelo
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()
' concluído?
If chaine.Trim().ToLower() = "fin" Then
terminé2 = True
Else
' faz-se a comparação
résultats = regex.Matches(chaine)
' sucesso?
If résultats.Count = 0 Then
Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
Else
' são exibidos os elementos que correspondem ao modelo
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))
' subelementos
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
'exibe
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
Veja um exemplo de execução:
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. O método Split
Já nos deparamos com esse método na classe String:
A string é vista como uma sequência de campos separados pelos caracteres presentes na tabela [separator]. O resultado é a tabela desses campos.
O separador de campos da cadeia é, neste caso, um dos caracteres da tabela separator. O método Split da classe Regex permite-nos definir o separador com base em um padrão:
A cadeia [input] é decomposta em campos, sendo estes separados por um separador correspondente ao modelo do objeto Regex atual. Suponhamos, por exemplo, que tenhamos em um arquivo de texto linhas da forma campo1, campo2, ..., campo n. Os campos são separados por uma vírgula, mas esta pode ser precedida ou seguida por espaços. O método Split da classe string não é adequado nesse caso. O método RegEx oferece a solução. Se linha for a linha lida, os campos poderão ser obtidos por
conforme mostra o exemplo a seguir:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Text.RegularExpressions
Module regex5
Sub Main()
' uma linha
Dim ligne As String = "abc , def , ghi"
' um modelo
Dim modèle As New Regex("\s*,\s*")
' decomposição da linha em campos
Dim champs As String() = modèle.Split(ligne)
' exibição
Dim i As Integer
For i = 0 To champs.Length - 1
Console.Out.WriteLine(("champs[" & i & "]=[" & champs(i) & "]"))
Next i
End Sub
End Module
Resultados da execução:
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. As classes BinaryReader e BinaryWriter
As classes BinaryReader e BinaryWriter servem para ler e gravar arquivos binários. Consideremos o seguinte exemplo. Queremos escrever um programa que seria chamado da seguinte forma:
// sintaxe pg texto bin
// lê-se um arquivo de texto (texto) e armazena-se seu conteúdo em um
// arquivo binário
// o arquivo de texto contém linhas no formato nome : idade
// que serão armazenadas em uma estrutura string, int
O arquivo de texto tem o seguinte conteúdo:
O programa é o seguinte:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
' BinaryWriter()
Module bw1
' sintaxe pg texto bin
' lê-se um arquivo de texto (texto) e seu conteúdo é armazenado em um
' arquivo binário
' o arquivo de texto contém linhas no formato nome : idade
' que serão armazenadas em uma estrutura string, int
Sub Main(ByVal arguments() As String)
' são necessários 2 argumentos
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg texte binaire")
Environment.Exit(1)
End If
' abertura do arquivo de texto para leitura
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
' abertura do arquivo binário para gravação
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
' leitura do arquivo de texto - gravação do arquivo binário
' linha do arquivo de texto
Dim ligne As String
' separador dos campos da linha
Dim séparateur As New Regex("\s*:\s*")
' o formato da idade
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
' linha vazia?
If ligne.Trim() = "" Then
traitementFini = True
End If
' mais uma linha
If Not traitementFini Then
numLigne += 1
' uma linha nome: idade
champs = séparateur.Split(ligne)
' precisamos de 2 campos
If champs.Length <> 2 Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
' linha seguinte
traitementFini = True
End If
End If
If Not traitementFini Then
' o segundo campo deve ser um número inteiro >=0
If Not modAge.IsMatch(champs(1)) Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
' linha seguinte
traitementFini = True
End If
' gravamos os dados no arquivo binário
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
End If
'linha seguinte
ligne = input.ReadLine()
End While
' fechamento dos arquivos
input.Close()
output.Close()
End Sub
End Module
Vamos nos deter nas operações relacionadas à classe BinaryWriter:
- o objeto BinaryWriter é aberto pela operação
output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))
O argumento do construtor deve ser um fluxo (Stream). Aqui, trata-se de um fluxo construído a partir de um arquivo (FileStream), para o qual se fornece:
- (continuação)
- o nome
- a operação a ser realizada, neste caso FileMode.Create para criar o arquivo
- o tipo de acesso, neste caso FileAccess.Write para acesso em gravação ao arquivo
- a operação de gravação
' os dados são gravados no arquivo binário
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
A classe BinaryWriter possui diferentes métodos Write sobrecarregados para gravar os diversos tipos de dados simples
- a operação de fechamento do fluxo
Os resultados da execução anterior serão fornecidos pelo programa a seguir. Este também aceita dois argumentos:
' sintaxe pg bin texto
' lê-se um arquivo binário bin e seu conteúdo é armazenado em um arquivo de texto (texto)
' o arquivo binário possui uma estrutura string, int
' o arquivo de texto contém linhas no formato nome : idade
Portanto, realizamos a operação inversa. Lemos um arquivo binário para criar um arquivo de texto. Se o arquivo de texto gerado for idêntico ao arquivo original, saberemos que a conversão texto → binário → texto ocorreu corretamente. O código é o seguinte:
' opções
Option Strict On
Option Explicit On
' espaços de nomes
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
Module br1
' sintaxe pg bin texto
' lê-se um arquivo binário bin e seu conteúdo é armazenado em um arquivo de texto (texto)
' o arquivo binário tem uma estrutura string, int
' o arquivo de texto contém linhas no formato nome : idade
Sub Main(ByVal arguments() As String)
' são necessários 2 argumentos
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg binaire texte")
Environment.Exit(1)
End If
' abertura do arquivo binário para leitura
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
' abertura do arquivo de texto para gravação
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
' leitura do arquivo binário – gravação do arquivo de texto
Dim nom As String ' nom d'une personne
Dim age As Integer ' son âge
' ciclo de processamento do arquivo binário
While True
' leitura do nome
Try
nom = dataIn.ReadString()
Catch
' fim do arquivo
Exit Sub
End Try
' leitura da idade
Try
age = dataIn.ReadInt32()
Catch
Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
Exit Sub
End Try
' gravação no arquivo de texto
dataOut.WriteLine(nom & ":" & age)
System.Console.WriteLine(nom & ":" & age)
End While
' fechando tudo
dataIn.Close()
dataOut.Close()
End Sub
End Module
Vamos nos deter nas operações relacionadas à classe BinaryReader:
- o objeto BinaryReader é aberto pela operação
dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))
O argumento do construtor deve ser um fluxo (Stream). Aqui, trata-se de um fluxo construído a partir de um arquivo (FileStream), para o qual fornecemos:
- (continuação)
- o nome
- a operação a ser realizada, neste caso FileMode.Open para abrir um arquivo existente
- o tipo de acesso, neste caso FileAccess.Read para acesso em leitura ao arquivo
- a operação de leitura
A classe BinaryReader dispõe de diferentes métodos ReadXX para ler os diferentes tipos de dados simples
- a operação de fechamento do fluxo
Se executarmos os dois programas em sequência, transformando personnes.txt em personnes.bin e, em seguida, personnes.bin em personnes.txt2, obtemos:

