4. Clases .NET de uso común
A continuación presentamos algunas clases de la plataforma .NET que resultan interesantes, incluso para un principiante. En primer lugar, mostramos cómo obtener información sobre los cientos de clases disponibles.
4.1. Buscar ayuda con SDK.NET
4.1.1. wincv
Si solo se ha instalado SDK y no Visual Studio.NET, se podrá utilizar el programa wincv.exe, que normalmente se encuentra en el árbol de directorios del SDK, por ejemplo, C:\Archivos de programa\Microsoft Visual Studio .NET 2003\SDK\v1.1. Al ejecutar esta utilidad, aparece la siguiente interfaz:
![]() |
En (1) se escribe el nombre de la clase deseada. Esto muestra en (2) varios temas posibles. Se elige el que convenga y se obtiene el resultado en (3), en este caso la clase HashTable. Este método es adecuado si se conoce el nombre de la clase que se busca. Si se desea explorar la lista de posibilidades que ofrece la plataforma .NET o se puede utilizar el archivo HTML StartHere.htm, que también se encuentra directamente en la carpeta de instalación de SSK.Net, por ejemplo, C:\Archivos de programa\Microsoft Visual Studio .NET 2003\SDK\v1.

El enlace .NET Framework SDK Documentación es el que hay que seguir para obtener una visión general de las clases .NET:

Allí, seguiremos el enlace [Bibliothèque de classes]. En él se encuentra la lista de todas las clases de .NET:

Sigamos, por ejemplo, el enlace System.Collections. Este espacio de nombres agrupa diversas clases que implementan colecciones, entre ellas la clase HashTable:

Sigamos el enlace HashTable que aparece a continuación:

Obtenemos la siguiente página:

Fíjate en la posición de la mano. Apunta a un enlace que permite especificar el lenguaje deseado, en este caso Visual Basic.
Allí encontramos el prototipo de la clase, así como ejemplos de uso. Sigamos el enlace [Hashtable, membres] que aparece a continuación:

Se obtiene la descripción completa de la clase:

Este método es el mejor para descubrir SDK y sus clases. La herramienta WinCV resulta útil cuando ya se conoce un poco la clase y se han olvidado algunos de sus miembros. WinCV permite entonces encontrar rápidamente la clase y sus miembros.
4.2. Buscar ayuda sobre las clases con VS.NET
A continuación ofrecemos algunas indicaciones para encontrar ayuda con Visual Studio.NET
4.2.1. Opción Ayuda
Seleccionemos la opción [?] del menú.

Aparece la siguiente ventana:

En la lista desplegable, podemos elegir un filtro de ayuda. Aquí, seleccionaremos el filtro [Visual Basic].

Hay dos ayudas útiles:
- la ayuda sobre el propio lenguaje VB.NET (sintaxis)
- la ayuda sobre los classes.NET que puede utilizar el lenguaje VB.NET
Se puede acceder a la ayuda del lenguaje VB.NET a través de [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic]:

Se obtiene la siguiente página de ayuda:

A partir de ahí, las diferentes subsecciones nos permiten obtener ayuda sobre diversos temas de VB.NET. Prestaremos atención a los tutoriales de VB.NET:

Para acceder a las diferentes clases de la plataforma .NET, seleccionaremos la ayuda [Visual Studio.NET/.NET Framework].

Nos centraremos especialmente en la sección [Référence/Bibliothèque de classes]:

Supongamos que nos interesa la clase [ArrayList]. Se encuentra en el espacio de nombres [System.Collections]. Es importante saberlo; de lo contrario, se preferirá el método de búsqueda que se expone a continuación. Se obtiene la siguiente ayuda:

El enlace [ArrayList, classe] ofrece una visión general de la clase:

Este tipo de página existe para todas las clases. Ofrece un resumen de la clase con ejemplos. Para obtener una descripción de los miembros de la clase, se seguirá el enlace [ArrayList, membres]:

4.2.2. Ayuda/Índice

La opción [Aide/index] permite buscar ayuda más específica que la anterior. Basta con escribir la palabra clave que se busca:

La ventaja de este método con respecto al anterior es que no es necesario saber dónde se encuentra lo que se busca en el sistema de ayuda. Probablemente sea el método preferible cuando se realiza una búsqueda específica, mientras que el otro método es más adecuado para descubrir todo lo que ofrece la ayuda.
4.3. La clase String
La clase String presenta numerosas propiedades y métodos. He aquí algunos de ellos:
número de caracteres de la cadena | |
propiedad indexada por defecto. [String].Chars(i) es el carácter n.º i de la cadena | |
devuelve verdadero si la cadena termina en value | |
devuelve verdadero si la cadena comienza por el valor | |
devuelve verdadero si la cadena es igual a value | |
devuelve la primera posición en la cadena del valor value; la búsqueda comienza a partir del carácter n.º 0 | |
devuelve la primera posición en la cadena del valor de la cadena; la búsqueda comienza a partir del carácter n.º startIndex | |
método de clase: devuelve una cadena de caracteres, resultado de la concatenación de los valores de la matriz value con el separador separator | |
devuelve una cadena que es una copia de la cadena actual en la que el carácter oldChar ha sido sustituido por el carácter newChar | |
la cadena se considera una secuencia de campos separados por los caracteres presentes en la matriz separator. El resultado es la matriz de dichos campos | |
subcadena de la cadena actual que comienza en la posición startIndex y tiene length caracteres | |
convierte la cadena actual a minúsculas | |
convierte la cadena actual a mayúsculas | |
elimina los espacios iniciales y finales de la cadena actual |
Una cadena C puede considerarse como una matriz de caracteres. Así,
- C.Chars(i) es el carácter i de C
- C.Length es el número de caracteres de C
Consideremos el siguiente ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
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
' muestra
Sub affiche(ByVal msg As [String])
' muestra mensaje
Console.Out.WriteLine(msg)
End Sub
End Module
La ejecución da los siguientes 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]
Veamos un nuevo ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Module string2
Sub Main()
' la línea a analizar
Dim ligne As String = "un:deux::trois:"
' los separadores de campos
Dim séparateurs() As Char = {":"c}
' dividir
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
' unir
Console.Out.WriteLine(("join=[" + System.String.Join(":", champs) + "]"))
End Sub
End Module
y los resultados de la ejecución:
El método Split de la clase String permite dividir los campos de una cadena de caracteres en una matriz. La definición del método que se utiliza aquí es la siguiente:
matriz de caracteres. Estos caracteres representan los caracteres utilizados para separar los campos de la cadena de caracteres. Así, si la cadena es [champ1, champ2, champ3], se podrá utilizar separator=new char() {","c}. Si el separador es una secuencia de espacios, se utilizará separator=nothing. | |
matriz de cadenas de caracteres en la que cada elemento es un campo de la cadena. |
El método Join es un método estático de la clase String:
matriz de cadenas de caracteres | |
una cadena de caracteres que servirá como separador de campos | |
una cadena de caracteres formada por la concatenación de los elementos de la tabla value separados por la cadena separator. |
4.4. La clase Array
La clase Array implementa una matriz. En nuestro ejemplo utilizaremos las siguientes propiedades y métodos:
propiedad: número de elementos de la matriz | |
método de clase: devuelve la posición de value en la tabla ordenada array; busca a partir de la posición index y con length elementos | |
método de clase: copia los elementos de length de sourceArray a destinationArray; para ello, se crea destinationArray | |
método de clase: ordena la tabla array; esta debe contener un tipo de datos con una función de orden predeterminada (cadenas, números). |
El siguiente programa ilustra el uso de la clase Array:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Module test
Sub Main()
' lectura de los elementos de una matriz introducidos mediante el 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é
' pregunta
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' lectura de la respuesta
réponse = Console.ReadLine().Trim()
' fin de la entrada si la cadena está vacía
If réponse.Equals("") Then
Exit While
End If
' verificación de la entrada
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' si no hay error
If Not erreur Then
' nueva tabla para alojar el nuevo elemento
éléments2 = New Double(i) {}
' copia de la tabla antigua a la nueva
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' la nueva tabla se convierte en la antigua
éléments1 = éléments2
' ya no se necesita la nueva tabla
éléments2 = Nothing
' Inserción de un nuevo elemento
éléments1(i) = élément
' un elemento más en la tabla
i += 1
End If
End While
' visualización de la tabla sin ordenar
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
' ordenación de la tabla
System.Array.Sort(éléments1)
' Visualización de la tabla 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
' Búsqueda
While Not terminé
' pregunta
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' lectura y verificación de la respuesta
réponse = Console.ReadLine().Trim()
' ¿Terminado?
If réponse.Equals("") Then
Exit While
End If
' verificación
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' si no hay error
If Not erreur Then
' se busca el elemento en la tabla ordenada
i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
' Visualización de la respuesta
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
Los resultados en pantalla son los siguientes:
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) :
La primera parte del programa crea una matriz a partir de datos numéricos introducidos mediante el teclado. La matriz no puede dimensionarse de antemano, ya que se desconoce el número de elementos que introducirá el usuario. Por lo tanto, se trabaja con dos matrices: éléments1 y éléments2.
' nueva matriz para alojar el nuevo elemento
éléments2 = New Double(i) {}
' copia de la tabla antigua a la nueva
If i <> 0 Then
Array.Copy(éléments1, éléments2, i)
End If
' la nueva tabla se convierte en la tabla anterior
éléments1 = éléments2
' ya no se necesita la nueva tabla
éléments2 = Nothing
' Inserción de un nuevo elemento
éléments1(i) = élément
' un elemento más en la tabla
i += 1
La tabla éléments1 contiene los valores introducidos actualmente. Cuando el usuario añade un nuevo valor, se crea una tabla éléments2 con un elemento más que éléments1, se copia el contenido de éléments1 en éléments2 (Array.Copy), se hace que éléments1 «apunte» a éléments2 y, por último, se añade el nuevo elemento a éléments1. Se trata de un proceso complejo que puede simplificarse si, en lugar de utilizar una matriz de tamaño fijo (Array), se utiliza una matriz de tamaño variable (ArrayList).
La matriz se ordena con el método Array.Sort. Este método se puede invocar con diferentes parámetros que especifican las reglas de ordenación. Sin parámetros, se realiza por defecto una ordenación ascendente. Por último, el método Array.BinarySearch permite buscar un elemento en una matriz ordenada.
4.5. La clase ArrayList
La clase ArrayList permite implementar tablas de tamaño variable durante la ejecución del programa, algo que no permite la clase Array anterior. Estas son algunas de las propiedades y métodos más comunes:
crea una lista vacía | |
número de elementos de la colección | |
añade el objeto value al final de la colección | |
borra la lista | |
índice del objeto value en la lista o -1 si no existe | |
Lo mismo, pero buscando a partir del elemento n.º startIndex | |
Lo mismo, pero devuelve el índice de la última aparición de «value» en la lista | |
Lo mismo, pero buscando a partir del elemento n.º startIndex | |
elimina el objeto obj si existe en la lista | |
elimina el elemento index de la lista | |
devuelve la posición del objeto «value» en la lista o -1 si no se encuentra en ella. La lista debe estar ordenada | |
ordena la lista. Esta debe contener objetos con una relación de orden predefinida (cadenas, números) | |
ordena la lista según la relación de orden establecida por la función comparar |
Retomemos el ejemplo tratado con objetos de tipo Array y procesémoslo con objetos de tipo ArrayList:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Module test
Sub Main()
' lectura de los elementos de una tabla introducidos mediante el 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é
' pregunta
Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
' lectura de la respuesta
réponse = Console.ReadLine().Trim()
' fin de la entrada si la cadena está vacía
If réponse.Equals("") Then
Exit While
End If
' verificación de la entrada
Try
élément = Double.Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' si no hay error
If Not erreur Then
' un elemento más en la tabla
éléments.Add(élément)
End If
End While
' visualización de la tabla sin ordenar
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()
' visualización de la tabla 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
' Búsqueda
While Not terminé
' pregunta
Console.Out.Write("Elément cherché (rien pour arrêter) : ")
' lectura y verificación de la respuesta
réponse = Console.ReadLine().Trim()
' ¿Terminado?
If réponse.Equals("") Then
Exit While
End If
' verificación
Try
élément = [Double].Parse(réponse)
erreur = False
Catch
Console.Error.WriteLine("Saisie incorrecte, recommencez")
erreur = True
End Try
' si no hay error
If Not erreur Then
' se busca el elemento en la tabla ordenada
i = éléments.BinarySearch(élément)
' Visualización de la respuesta
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
Los resultados de la ejecución son los siguientes:
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. La clase Hashtable
La clase Hashtable permite implementar un diccionario. Se puede considerar un diccionario como una tabla de dos columnas:
![]() |
Las claves son únicas, c.a.d. no puede haber dos claves idénticas. Los principales métodos y propiedades de la clase Hashtable son los siguientes:
crea un diccionario vacío | |
añade una entrada (clave, valor) al diccionario, donde clave y valor son referencias a objetos. | |
elimina del diccionario la línea clave=key | |
vacía el diccionario | |
devuelve verdadero (true) si la clave key pertenece al diccionario. | |
| devuelve verdadero (true) si el valor value pertenece al diccionario. |
propiedad: número de elementos del diccionario (clave, valor) | |
propiedad: colección de claves del diccionario | |
propiedad: colección de valores del diccionario | |
propiedad indexada: permite conocer o establecer el valor asociado a una clave |
Consideremos el siguiente programa de ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
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}
' rellenar el diccionario
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 en el diccionario
Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
' lista de claves
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 claves y 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
' se elimina la clave «paul»
Console.Out.WriteLine("[Suppression d'une clé]")
dico.Remove("paul")
' lista de claves y 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
' búsqueda en el diccionario
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
' siguiente búsqueda
Console.Out.Write("Nom recherché (rien pour arrêter) : ")
nomCherché = Console.ReadLine().Trim()
End While
End Sub
End Module
Los resultados de la ejecución son los siguientes:
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) :
El programa también utiliza un objeto IEnumerator para recorrer las colecciones de claves y valores del diccionario de tipo ICollection (véanse más arriba las propiedades Keys y Values). Una colección es un conjunto de objetos que se puede recorrer. La interfaz ICollection se define de la siguiente manera:

La propiedad Count nos permite conocer el número de elementos de la colección. La interfaz ICollection deriva de la interfaz IEnumerable:

Esta interfaz solo tiene un método, GetEnumerator, que nos permite obtener un objeto de tipo IEnumerator:

El método GetEnumerator() de una colección ICollection nos permite recorrer la colección con los siguientes métodos:
se sitúa en el siguiente elemento de la colección. Devuelve «true» si dicho elemento existe, y «false» en caso contrario. El primer MoveNext se sitúa en el primer elemento. El elemento «actual» de la colección está entonces disponible en la propiedad Current del enumerador | |
propiedad: elemento actual de la colección | |
reposiciona el enumerador al inicio de la colección, c.a.d, antes del primer elemento. |
La estructura de iteración sobre los elementos de una colección (ICollection) C es, por lo tanto, la siguiente:
' definir la colección
dim C as ICollection C=...
' obtener un enumerador de esta colección
dim itérateur as IEnumerator=C.GetEnumerator();
' recorrer la colección con este enumerador
while(itérateur.MoveNext())
' tenemos un elemento actual
' utilizar itérateur.Current
end while
4.7. La clase StreamReader
La clase StreamReader permite leer el contenido de un archivo. Estas son algunas de sus propiedades y métodos:
abre un flujo a partir del archivo path. Se lanza una excepción si este no existe | |
cierra el flujo | |
lee una línea del flujo abierto | |
lee el resto del flujo desde la posición actual |
He aquí un ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Imports System.IO
Module test
Sub Main()
Dim ligne As String = Nothing
Dim fluxInfos As StreamReader = Nothing
' lectura del contenido del archivo
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
y sus resultados de ejecución:
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. La clase StreamWriter
La clase StreamWriter permite escribir en un archivo. Estas son algunas de sus propiedades y métodos:
abre un flujo de escritura a partir del archivo path. Se lanza una excepción si no se puede crear | |
si es verdadero, la escritura en el flujo no pasa por un búfer; de lo contrario, la escritura en el flujo no es inmediata: primero se escribe en un búfer y luego en el flujo cuando el búfer está lleno. Por defecto se utiliza el modo con búfer. Es adecuado para flujos de archivo, pero generalmente no para flujos de red. | |
para establecer o conocer el carácter de fin de línea que debe utilizar el método WriteLine | |
cierra el flujo | |
escribe una línea en el flujo de escritura | |
escribe el búfer en el flujo |
Consideremos el siguiente ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
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
' creación del archivo de texto
fluxInfos = New StreamWriter("infos.txt")
' lectura de la línea introducida mediante el teclado
Console.Out.Write("ligne (rien pour arrêter) : ")
ligne = Console.In.ReadLine().Trim()
' bucle mientras la línea introducida no esté vacía
While ligne <> ""
' escritura de la línea en el archivo de texto
fluxInfos.WriteLine(ligne)
' lectura de una nueva línea del 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
' cierre del archivo
Try
fluxInfos.Close()
Catch
End Try
End Try
End Sub
End Module
y los resultados de la ejecución:
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. La clase Regex
La clase Regex permite el uso de expresiones regulares. Estas permiten comprobar el formato de una cadena de caracteres. Así, se puede verificar que una cadena que representa una fecha tenga el formato dd/mm/aa. Para ello, se utiliza un patrón y se compara la cadena con dicho patrón. Así, en este ejemplo, d, m y a deben ser números. El patrón de un formato de fecha válido es entonces «\d\d/\d\d/\d\d», donde el símbolo \d designa un dígito. Los símbolos que se pueden utilizar en un patrón son los siguientes (documentación de Microsoft):
Descripción | |
Marca el carácter siguiente como carácter especial o literal. Por ejemplo, «n» corresponde al carácter «n». «\n» corresponde a un carácter de nueva línea. La secuencia «\\» corresponde a «\», mientras que «\»(» corresponde a «(». | |
Corresponde al inicio de la entrada. | |
Corresponde al final de la entrada. | |
Corresponde al carácter anterior cero o más veces. Así, «zo*» corresponde a «z» o a «zoo». | |
Corresponde al carácter anterior una o varias veces. Así, «zo+» corresponde a «zoo», pero no a «z». | |
Corresponde al carácter anterior cero o una vez. Por ejemplo, «a?ve?» corresponde a «ve» en «lever». | |
Coincide con cualquier carácter único, excepto el carácter de nueva línea. | |
| Busca el modèle y memoriza la coincidencia. La subcadena correspondiente se puede extraer de la colección Matches obtenida, utilizando el elemento [0]...[n]. Para encontrar coincidencias con caracteres entre paréntesis ( ), utilice "\(" o "\)". |
| Corresponde a x o a y. Por ejemplo, «z|foot» corresponde a «z» o a «foot». «(z|f)oo» corresponde a «zoo» o a «foo». |
| n es un número entero no negativo. Corresponde exactamente a n multiplicado por el carácter. Por ejemplo, «o{2}» no corresponde a la «o» de «Bob», sino a las dos primeras «o» de «fooooot». |
| n es un número entero no negativo. Corresponde al menos a n veces el carácter. Por ejemplo, «o{2,}» no coincide con la «o» de «Bob», sino con todas las «o» de «fooooot». «o{1,}» equivale a «o+» y «o{0,}» equivale a «o*». |
| m y n son números enteros no negativos. Corresponde al menos a n y como máximo a m veces el carácter. Por ejemplo, «o{1,3}» corresponde a las tres primeras «o» de «foooooot» y «o{0,1}» equivale a «o?». |
| Conjunto de caracteres. Corresponde a uno de los caracteres indicados. Por ejemplo, «[abc]» corresponde a «a» en «plat». |
| Conjunto de caracteres negativo. Corresponde a cualquier carácter no indicado. Por ejemplo, «[^abc]» corresponde a «p» en «plat». |
| Rango de caracteres. Corresponde a cualquier carácter de la serie especificada. Por ejemplo, «[a-z]» corresponde a cualquier carácter alfabético minúsculo comprendido entre «a» y «z». |
| Rango de caracteres negativo. Corresponde a cualquier carácter que no se encuentre en la serie especificada. Por ejemplo, «[^m-z]» corresponde a cualquier carácter que no se encuentre entre «m» y «z». |
Corresponde a un límite que representa una palabra, es decir, a la posición entre una palabra y un espacio. Por ejemplo, «er\b» corresponde a «er» en «lever», pero no a «er» en «verbe». | |
Corresponde a un límite que no representa una palabra. «en*t\B» corresponde a «ent» en «bien entendu». | |
Corresponde a un carácter que representa un número. Equivale a [0-9]. | |
Corresponde a un carácter que no representa un número. Equivale a [^0-9]. | |
Corresponde a un carácter de salto de página. | |
Corresponde a un carácter de nueva línea. | |
Corresponde a un carácter de retorno de carro. | |
Corresponde a cualquier espacio en blanco, incluyendo el espacio, la tabulación, el salto de página, etc. Equivale a «[ \f\n\r\t\v]». | |
Corresponde a cualquier carácter de espacio no en blanco. Equivale a «[^ \f\n\r\t\v]». | |
Corresponde a un carácter de tabulación. | |
Corresponde a un carácter de tabulación vertical. | |
Corresponde a cualquier carácter que represente una palabra e incluya un guión bajo. Equivale a «[A-Za-z0-9_]». | |
Corresponde a cualquier carácter que no represente una palabra. Equivale a «[^A-Za-z0-9_]». | |
| Corresponde a num, donde num es un número entero positivo. Hace referencia a las coincidencias memorizadas. Por ejemplo, «(.)\1» corresponde a dos caracteres idénticos consecutivos. |
| Corresponde a n, donde n es un valor de escape octal. Los valores de escape octales deben tener 1, 2 o 3 dígitos. Por ejemplo, «\11» y «\011» corresponden ambos a un carácter de tabulación. «\0011» equivale a «\001» y «1». Los valores de escape octales no deben superar 256. Si fuera así, solo se tendrían en cuenta los dos primeros dígitos en la expresión. Permite utilizar los códigos ASCII en expresiones regulares. |
| Corresponde a n, donde n es un valor de escape hexadecimal. Los valores de escape hexadecimales deben constar obligatoriamente de dos dígitos. Por ejemplo, «\x41» corresponde a «A». «\x041» equivale a «\x04» y «1». Permite utilizar los códigos ASCII en expresiones regulares. |
Un elemento de una plantilla puede aparecer una o varias veces. Veamos algunos ejemplos relacionados con el símbolo \d, que representa un dígito:
plantilla | significado |
un dígito | |
0 o 1 dígito | |
0 o más dígitos | |
1 o más dígitos | |
2 dígitos | |
al menos 3 dígitos | |
entre 5 y 7 dígitos |
Imaginemos ahora el modelo capaz de describir el formato esperado para una cadena de caracteres:
cadena buscada | 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 | |
Se puede especificar dónde se busca el patrón en la cadena:
patrón | significado |
el patrón comienza la cadena | |
el modelo termina la cadena | |
la plantilla comienza y termina la cadena | |
el patrón se busca en toda la cadena, comenzando por el principio de la misma. |
cadena buscada | patrón |
!$ | |
\.$ | |
^// | |
^\s*\w+\s*$ | |
^\s*\w+\s*\w+\s*$ | |
\bsecret\b |
Los subconjuntos de un patrón pueden «recuperarse». De este modo, no solo se puede comprobar si una cadena se ajusta a un patrón concreto, sino que también se pueden extraer de dicha cadena los elementos que corresponden a los subconjuntos del patrón que se han rodeado de paréntesis. Así, si se analiza una cadena que contiene una fecha dd/mm/aa y se desea además recuperar los elementos dd, mm, aa de dicha fecha, se utilizará el patrón (\d\d)/(\d\d)/(\d\d).
4.9.1. Comprobar que una cadena se ajusta a un patrón dado
Un objeto de tipo Regex se construye de la siguiente manera:
El constructor crea un objeto «expresión regular» a partir de un patrón pasado como parámetro (pattern). Una vez construida la expresión regular modelo, se puede comparar con cadenas de caracteres mediante el método IsMatch:
IsMatch devuelve verdadero si la cadena de entrada coincide con el patrón de la expresión regular. A continuación se muestra un ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex1
Sub Main()
' una expresión regular de patrón
Dim modèle1 As String = "^\s*\d+\s*$"
Dim regex1 As New Regex(modèle1)
' comparar un ejemplar con el patrón
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
' mostrar
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
y los resultados de la ejecución:
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. Buscar todos los elementos de una cadena que coincidan con un patrón
El método Matches
devuelve una colección de elementos de la cadena input que coinciden con el patrón, tal y como se muestra en el siguiente ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' varias ocurrencias del patrón en el ejemplo
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
'muestra
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
La clase MatchCollection tiene una propiedad Count que es el número de elementos de la colección. Si résultats es un objeto MatchCollection, résultats(i) es el elemento i de esta colección y es de tipo Match. En nuestro ejemplo, résultats es el conjunto de elementos de la cadena exemplaire3 que corresponden al modelo modèle2, y résultats(i) es uno de esos elementos. La clase Match tiene dos propiedades que nos interesan aquí:
- Value: el valor del objeto Match, es decir, el elemento correspondiente al modelo
- Index: la posición en la que se ha encontrado el elemento en la cadena explorada
Resultados de la ejecución del 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 un patrón
Se pueden «extraer» subconjuntos de un patrón. De este modo, no solo se puede comprobar si una cadena se ajusta a un patrón concreto, sino que también se pueden extraer de dicha cadena los elementos correspondientes a los subconjuntos del patrón que se han rodeado de paréntesis. Así, si se analiza una cadena que contiene una fecha dd/mm/aa y se desea además extraer los elementos dd, mm y aa de dicha fecha, se utilizará el patrón (\d\d)/(\d\d)/(\d\d). Veamos el siguiente ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Module regex2
Sub Main()
' captura de elementos en la plantilla
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"
' verificación de la plantilla
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' la copia se ajusta a la plantilla
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' se muestran los 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
' el ejemplar no se corresponde con el modelo
affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
End If
End Sub
'muestra
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
La ejecución de este programa produce los siguientes 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
La novedad se encuentra en la siguiente parte del código:
' verificación del modelo
Dim résultat As Match = regex3.Match(exemplaire4)
If résultat.Success Then
' el ejemplar se corresponde con el modelo
affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
' se muestran los 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
La cadena exemplaire4 se compara con el modelo regex3 mediante el método Match. Este devuelve un objeto Match ya presentado. Aquí utilizamos dos nuevas propiedades de esta clase:
- Success: indica si ha habido coincidencia
- Groups: colección en la que
- Groups[0] corresponde a la parte de la cadena que se ajusta al patrón
- Groups[i] (i>=1) corresponde al grupo de paréntesis n.º i
Si el resultado es del tipo Match, résultats.Groups es del tipo GroupCollection y résultats.Groups[i] es del tipo Group. La clase Group tiene dos propiedades que utilizamos aquí:
- Value: el valor del objeto Group que contiene el elemento correspondiente al contenido de un paréntesis
- Index: la posición en la que se ha encontrado el elemento en la cadena explorada
4.9.4. Un programa de aprendizaje
Encontrar la expresión regular que nos permita verificar que una cadena se ajusta a un determinado patrón es, a veces, todo un reto. El siguiente programa permite practicar. Solicita un patrón y una cadena y, a continuación, indica si la cadena se ajusta o no al patrón.
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic
Module regex4
Sub Main()
' una expresión regular de plantilla
Dim modèle, chaine As String
Dim regex As Regex = Nothing
Dim résultats As MatchCollection
' se solicita al usuario los modelos y los ejemplares que se deben comparar con este
Dim terminé1 As Boolean = False
Do While Not terminé1
Dim erreur As Boolean = True
Do While Not terminé1 And erreur
' se solicita el patrón
Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
modèle = Console.In.ReadLine()
' ¿Terminado?
If modèle.Trim().ToLower() = "fin" Then
terminé1 = True
Else
' se crea la expresión regular
Try
regex = New Regex(modèle)
erreur = False
Catch ex As Exception
Console.Error.WriteLine(("Erreur : " + ex.Message))
End Try
End If
Loop
' ¿Terminado?
If terminé1 Then Exit Sub
' se le pide al usuario los ejemplares que se van a comparar con el 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()
' ¿Terminado?
If chaine.Trim().ToLower() = "fin" Then
terminé2 = True
Else
' se realiza la comparación
résultats = regex.Matches(chaine)
' ¿Éxito?
If résultats.Count = 0 Then
Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
Else
' se muestran los elementos que coinciden con el 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
'muestra
Sub affiche(ByVal msg As String)
Console.Out.WriteLine(msg)
End Sub
End Module
He aquí un ejemplo de ejecución:
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. El método Split
Ya hemos visto este método en la clase String:
La cadena se considera una secuencia de campos separados por los caracteres presentes en la tabla [separator]. El resultado es la tabla de dichos campos.
El separador de campos de la cadena es aquí uno de los caracteres de la tabla separator. El método Split de la clase Regex nos permite expresar el separador en función de un patrón:
La cadena [input] se descompone en campos, separados por un separador que se ajusta al modelo del objeto Regex actual. Supongamos, por ejemplo, que tenemos en un archivo de texto líneas con el formato campo1, campo2, ..., campo n. Los campos están separados por una coma, pero esta puede ir precedida o seguida de espacios. El método Split de la clase string no es adecuado en este caso. El método RegEx ofrece la solución. Si línea es la línea leída, los campos se pueden obtener mediante
tal y como se muestra en el siguiente ejemplo:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Text.RegularExpressions
Module regex5
Sub Main()
' una línea
Dim ligne As String = "abc , def , ghi"
' una plantilla
Dim modèle As New Regex("\s*,\s*")
' desglose de línea en campos
Dim champs As String() = modèle.Split(ligne)
' visualización
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 de la ejecución:
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. Las clases BinaryReader y BinaryWriter
Las clases BinaryReader y BinaryWriter sirven para leer y escribir archivos binarios. Consideremos la siguiente aplicación. Queremos escribir un programa que se llamaría de la siguiente manera:
// sintaxis pg texto bin
// se lee un archivo de texto (texto) y se almacena su contenido en un
// archivo binario
// El archivo de texto contiene líneas con el formato nombre: edad
// que se almacenarán en una estructura de tipo string, int
El archivo de texto tiene el siguiente contenido:
El programa es el siguiente:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
' BinaryWriter()
Module bw1
' sintaxis pg texto bin
' se lee un archivo de texto (texto) y se almacena su contenido en un
' archivo binario
' el archivo de texto tiene líneas con el formato nombre : edad
' que se almacenarán en una estructura string, int
Sub Main(ByVal arguments() As String)
' se necesitan 2 argumentos
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg texte binaire")
Environment.Exit(1)
End If
' apertura del archivo de texto en modo lectura
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
' apertura del archivo binario en modo escritura
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
' lectura del archivo de texto - escritura del archivo binario
' línea del archivo de texto
Dim ligne As String
' separador de campos de la línea
Dim séparateur As New Regex("\s*:\s*")
' el formato de la edad
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
' ¿línea vacía?
If ligne.Trim() = "" Then
traitementFini = True
End If
' una línea más
If Not traitementFini Then
numLigne += 1
' una línea nombre: edad
champs = séparateur.Split(ligne)
' necesitamos 2 campos
If champs.Length <> 2 Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
' línea siguiente
traitementFini = True
End If
End If
If Not traitementFini Then
' el segundo campo debe ser un entero >=0
If Not modAge.IsMatch(champs(1)) Then
Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
' línea siguiente
traitementFini = True
End If
' escribimos los datos en el archivo binario
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
End If
'línea siguiente
ligne = input.ReadLine()
End While
' cierre de los archivos
input.Close()
output.Close()
End Sub
End Module
Centrémonos en las operaciones relacionadas con la clase BinaryWriter:
- el objeto BinaryWriter se abre mediante la operación
output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))
El argumento del constructor debe ser un flujo (Stream). En este caso, se trata de un flujo creado a partir de un archivo (FileStream) del que se proporciona:
- (continuación)
- el nombre
- la operación a realizar, aquí FileMode.Create para crear el archivo
- el tipo de acceso, en este caso FileAccess.Write para un acceso de escritura al archivo
- la operación de escritura
' se escriben los datos en el archivo binario
output.Write(champs(0))
output.Write(Integer.Parse(champs(1)))
La clase BinaryWriter dispone de diferentes métodos Write sobrecargados para escribir los diferentes tipos de datos simples
- la operación de cierre del flujo
Los resultados de la ejecución anterior nos los proporcionará el siguiente programa. Este también acepta dos argumentos:
' sintaxis pg bin texto
' se lee un archivo binario bin y se guarda su contenido en un archivo de texto (texto)
' el archivo binario tiene una estructura string, int
' el archivo de texto tiene líneas con el formato nombre : edad
Por lo tanto, realizamos la operación inversa. Leemos un archivo binario para crear un archivo de texto. Si el archivo de texto resultante es idéntico al archivo original, sabremos que la conversión texto --> binario --> texto se ha realizado correctamente. El código es el siguiente:
' opciones
Option Strict On
Option Explicit On
' espacios de nombres
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
Module br1
' sintaxis pg bin texto
' se lee un archivo binario bin y se guarda su contenido en un archivo de texto (texto)
' el archivo binario tiene una estructura string, int
' el archivo de texto tiene líneas con el formato nombre : edad
Sub Main(ByVal arguments() As String)
' se necesitan 2 argumentos
Dim nbArgs As Integer = arguments.Length
If nbArgs <> 2 Then
Console.Error.WriteLine("syntaxe : pg binaire texte")
Environment.Exit(1)
End If
' apertura del archivo binario en modo lectura
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
' apertura del archivo de texto en modo escritura
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
' lectura del archivo binario - escritura del archivo de texto
Dim nom As String ' nom d'une personne
Dim age As Integer ' son âge
' bucle de procesamiento del archivo binario
While True
' lectura del nombre
Try
nom = dataIn.ReadString()
Catch
' fin del archivo
Exit Sub
End Try
' lectura de edad
Try
age = dataIn.ReadInt32()
Catch
Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
Exit Sub
End Try
' escritura en archivo de texto
dataOut.WriteLine(nom & ":" & age)
System.Console.WriteLine(nom & ":" & age)
End While
' se cierra todo
dataIn.Close()
dataOut.Close()
End Sub
End Module
Centrémonos en las operaciones relacionadas con la clase BinaryReader:
- el objeto BinaryReader se abre mediante la operación
dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))
El argumento del constructor debe ser un flujo (Stream). En este caso, se trata de un flujo creado a partir de un archivo (FileStream) del que se proporciona:
- (continuación)
- el nombre
- la operación a realizar, aquí FileMode.Open para abrir un archivo existente
- el tipo de acceso, en este caso FileAccess.Read para un acceso de lectura al archivo
- la operación de lectura
La clase BinaryReader dispone de diferentes métodos ReadXX para leer los diferentes tipos de datos simples
- la operación de cierre del flujo
Si se ejecutan los dos programas en cadena, transformando personnes.txt en personnes.bin y luego personnes.bin en personnes.txt2, se obtiene:

