Clases String adicionales
La clase String es intuitiva y fácil de usar. Podemos utilizar sus métodos para examinar fácilmente las cadenas, eliminar secciones, recortar el inicio o el final de una cadena y extraer subcadenas. Sin embargo, la forma inusual en que se introducen cadenas en nuestro programa, las hace ineficaces para algunos propósitos. La figura muestra el programa de ejemplo de permutaciones.
Este programa muestra una cadena grande que contiene todas las permutaciones de un conjunto de letras entre la A y la H. Hay 8 letras y (5040 permutaciones de esas ocho letras) por lo que el resultado es 5040 cadenas concatenadas. Para empeorar las cosas, el programa crea cada permutación con un carácter cada vez, por lo que cada permutación requiere la construcción de ocho cadenas más pequeñas. Esto significa que el programa construye 8 × 5040 = 40.320 cadenas en total, cada una de las cuales debe ser ingresada. Como resultado, el programa es bastante lento, tardando aproximadamente 23 segundos en producir estas 5.040 permutaciones utilizando la concatenación de cadenas. Para casos especiales como este, cuando la clase String es particularmente ineficiente, un programa puede obtener un mejor rendimiento utilizando las clases de procesamiento de cadenas especializadas:
StringBuilder
StringWriter
StringReader
El programa tomó solo 0.05 segundos para construir las permutaciones cuando utilizamos StringBuilder en lugar de concatenaciones de String. Cada una de estas clases de procesamiento de cadenas se describe en las siguientes secciones.
StringBuilder
La clase StringBuilder representa una cadena mutable no internada. Almacena datos de caracteres en una matriz y puede agregar, eliminar, reemplazar y agregar caracteres sin crear un nuevo objeto String o usar el grupo interno. Normalmente, un programa usa un StringBuilder para construir una cadena en una larga serie de pasos y luego llama al método ToString de StringBuilder para convertir el resultado en una cadena normal. Por ejemplo, el siguiente código utiliza StringBuilder para construir una cadena que contiene una serie de nombres de empleados en líneas separadas:
String[]
NombresEmpleados =
{
"Abel",
"Bartolo",
"Carlos",
"David",
};
StringBuilder allNames = New
StringBuilder();
foreach (string name
in
NombresEmpleados)
{
allNames.Append("[" + name + "]" + Environment.NewLine);
}
txtEmpleados.Text
= allNames.ToString();
El código comienza definiendo una matriz de nombres de empleados. Luego crea un StringBuilder y recorre los nombres en la matriz NombresEmpleados. Para cada nombre, el código llama al método Append de StringBuilder para agregar el nombre entre corchetes a la cadena. Una vez que ha procesado todos los nombres, el código llama al método ToString de StringBuilder para convertirlo en un String normal y muestra el resultado en la caja de texto txtEmpleados.
La Tabla describe las propiedades más útiles de la clase StringBuilder.
Propiedad |
Descripción |
Capacity |
Obtiene o establece el número de
caracteres que puede contener StringBuilder. Si la cantidad de texto almacenado
en StringBuilder excede esta cantidad, el objeto asigna más espacio. Si
sabe que StringBuilder debe contener al menos un cierto número de caracteres,
podemos utilizar esta propiedad para hacer que el objeto se preasigne memoria en lugar de asignar memoria
de forma incremental. Algunas versiones sobrecargadas del constructor de la
clase permiten especificar una
capacidad inicial. |
Length |
Obtiene
o establece el número actual de caracteres almacenados en StringBuilder. Si
establecemos este valor a un menor valor que la longitud actual, el texto en StringBuilder se trunca. |
El indexador de StringBuilder devuelve los caracteres almacenados en el objeto. Un programa puede usar el indexador para obtener y establecer valores de caracteres. Por ejemplo, la declaración allNames [10] = 'X' establece el carácter número 10 en X.
La tabla describe los métodos más útiles de la clase StringBuilder.
Método |
Descripción
|
Append |
Añade
una representación de cadena de un objeto al final del texto de StringBuilder |
AppendFormat |
Formatea
una serie de objetos y agrega el resultado al final del texto de StringBuilder |
EnsureCapacity |
Garantiza que StringBuilder tenga al menos una
capacidad determinada |
Insert |
Inserta
una representación de cadena de un objeto en una posición dada en el texto de
StringBuilder |
Remove |
Elimina
un rango de caracteres del texto de StringBuilder |
Replace |
Reemplaza todas las
instancias de un carácter o cadena con un nuevo carácter o cadena |
ToString |
Devuelve
una representación de cadena normal del texto de StringBuilder |
La clase StringBuilder agrega algo de sobrecarga a un programa y, a veces, hace que el código sea más difícil de leer, por lo que generalmente debemos usarlo solo si realizamos una gran cantidad de operaciones de cadena. En un conjunto de pruebas, la concatenación de cadenas simple fue más rápida que la creación y el uso de StringBuilder para menos de aproximadamente siete concatenaciones.
También hay que tener en cuenta en cuenta que los tiempos involucrados para algunas operaciones de cadena son pequeños. Pero utilizar StringBuilder para concatenar 10 cadenas puede ser un poco más rápido que realizar 10 concatenaciones simples de cadena, pero la cantidad total de tiempo ahorrado se mide en milisegundos. A menos que el programa repita esa operación muchas veces o haga concatenaciones mucho más largas, podemos sacrificar algunos milisegundos para que el código sea más fácil de entender.
StringWriter
La clase StringWriter proporciona una interfaz que facilita en algunos casos la creación de una cadena en un StringBuilder subyacente. La clase StringWriter proporciona métodos que facilitan la escritura secuencial de valores en una cadena. La tabla describe los métodos más útiles de StringWriter.
Método
|
Descripción |
Flush |
Vacía los datos almacenados en búfer
en el StringWriter subyacente |
ToString |
Devuelve el contenido actual del
objeto como una cadena |
Write |
Añade un elemento a los datos de la
cadena. Las versiones sobrecargadas agregan char,
string, int, double y
otros muchos tipos de datos. |
WriteAsync |
Anexa
de forma asíncrona un char,string o una matriz de caracteres al final
de los datos de la cadena |
WriteLine |
Agrega
un elemento a los datos de la cadena como lo hace Write y luego agrega una
nueva línea |
StringWriter puede ser útil cuando solo deseamos agregar valores a una cadena. StringWriter también implementa una interfaz TextWriter, lo que puede ser útil cuando otras clases requieren un TextWriter para producir una salida y deseamos almacenar esa salida en una cadena. Por ejemplo, el método Serialize de la clase XmlSerializer envía la salida a un TextWriter. Si queremos serializar en una cadena, podemos enviar la salida a StringWriter y luego usar el método ToString de StringWriter para obtener el resultado. Si necesita manipular los datos de la cadena subyacente de otras formas, como eliminar o reemplazar caracteres, StringBuilder proporciona más flexibilidad.
StringReader
La clase StringReader proporciona una implementación TextReader que lee fragmentos de datos tomados de un StringBuilder subyacente. Proporciona métodos que facilitan la lectura secuencial de fragmentos de texto de una cadena. La tabla describe los métodos más útiles de StringReader.
Método
|
Descripción |
Peek |
Devuelve
el siguiente carácter en los datos pero no avanza al carácter |
Read |
Devuelve el siguiente carácter de
los datos y avanza al siguiente carácter. Una versión sobrecargada puede leer
un bloque de caracteres |
ReadAsync |
Lee de
forma asíncrona caracteres de StringReader en un búfer |
ReadBlock |
Lee
hasta un número máximo de caracteres de StringReader
en un búfer que
comienza en un índice especificado |
ReadBlockAsync |
Lee asincrónicamente hasta un número
máximo de carácteres de StringReader en un búfer que comienza en un índice
especificado. |
ReadLine |
Lee
carácteres de StringReader hasta que encuentra el final de
línea |
ReadLineAsync |
Lee
de forma asíncrona los caracteres de StringReader hasta que encuentra el fin de la
línea |
ReadToEnd |
Devuelve el texto
restante de StringReader como una cadena |
ReadToEndAsync |
Devuelve
de forma asíncrona el texto restante de StringReader como una cadena |
La clase StringReader proporciona acceso a los datos de StringBuilder a un nivel relativamente bajo. A menudo, un programa usa un StringReader solo porque necesita pasar información a un método predefinido que requiere un StringReader o TextReader como parámetro.
Veamos un ejemplo: Usando StringBuilder
Usando solo StringBuilders (sin Strings), escribir un programa que muestre todas las subsecuencias iniciales de las letras del alfabeto A, AB, ABC, y así sucesivamente en un TextBox, como se muestra en la figura
Private void
Form1_Load(Object sender, EventArgs e)
{
// Genera un StringBuilder sosteniendo los ABC
StringBuilder letters =
New StringBuilder("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
// Éste contiene la siguiente línea de letras.
StringBuilder line = New
StringBuilder();
//
Crea el resultado StringBuilder.
StringBuilder
result = New StringBuilder();
//
Recorre las letras.
For
(int i = 0; i < 26; i++)
{
// Agregua la siguiente letra
a la línea.
line.Append(letters[i]);
//Agrega una línea al resultado.
result.AppendLine(line.ToString());
}
// Muestra el resultado.
stringBuilderTextBox.Text = result.ToString();
stringBuilderTextBox.Select(0,
0);
}
El código construye un StringBuilder que contiene las letras del alfabeto. Hace un segundo StringBuilder para mantener una línea de salida y un tercero para mantener el resultado final. A continuación, el código recorre los números del 0 al 25. Para cada valor de i, el código agrega el i-ésimo carácter en letras al valor en línea. Luego agrega el nuevo valor de línea al resultado, siguiéndolo con una nueva línea. Cuando el código termina su ciclo, muestra el resultado. En este ejemplo, no está claro si usar StringBuilder es más rápido que usar concatenaciones de cadenas simples. En una prueba que ejecutó este código y un código similar que realizó concatenaciones de cadenas 100.000 veces, la versión de StringBuilder tomó aproximadamente el 54 por ciento de tiempo, por lo que hay un ahorro de tiempo, pero el resultado para una sola ejecución es insignificante.
No hay comentarios:
Publicar un comentario