.net stringbuilder stringwriter

.net - StringWriter o StringBuilder



(7)

¿Cuál es la diferencia entre StringWriter y StringBuilder y cuándo debería usar uno u otro?


La clase StringBuilder es básicamente una cadena mutable, una clase auxiliar para construir una cadena inmutable. El StringWriter está construido en la parte superior para agregar más funciones de conveniencia para el formateo de cadenas.


No creo que ninguna de las respuestas existentes realmente responda la pregunta. La relación real entre las dos clases es un ejemplo del patrón de adaptador .

StringWriter implementa todos sus métodos de Write... reenviando a una instancia de StringBuilder que almacena en un campo. Esto no es simplemente un detalle interno, porque StringWriter tiene un método público GetStringBuilder que devuelve el generador de cadenas interno, y también un constructor que le permite pasar un StringBuilder existente.

Así que StringWriter es un adaptador que permite que StringBuilder se use como un destino por código que espera trabajar con un TextWriter . En términos de comportamiento básico, claramente no hay nada que elegir entre ellos ... a menos que pueda medir la sobrecarga de reenviar las llamadas, en cuyo caso StringWriter es un poco más lento, pero parece muy poco probable que sea significativo.

Entonces, ¿por qué no hicieron que StringBuilder implementara TextWriter directamente? Esta es un área gris, porque la intención detrás de una interfaz no siempre es clara a primera vista.

TextWriter es casi una interfaz para algo que acepta una secuencia de caracteres. Pero tiene una arruga adicional: una propiedad llamada Encoding . Esto implica que TextWriter es una interfaz para algo que acepta una secuencia de caracteres y también los convierte en bytes .

Esto es un vestigio inútil en StringWriter porque no realiza codificación. La Encoding dice:

Esta propiedad es necesaria para algunos escenarios XML donde se debe escribir un encabezado que contenga la codificación utilizada por StringWriter. Esto permite que el código XML consuma un StringWriter arbitrario y genere el encabezado XML correcto.

Pero eso no puede ser correcto, porque no hay forma de que especifiquemos el valor de Encoding for StringWriter . La propiedad siempre tiene el valor UnicodeEncoding . En consecuencia, cualquier código que examinara esta propiedad para construir un encabezado XML siempre diría utf-16 . Por ejemplo:

var stringWriter = new StringWriter(); using (var xmlWriter = XmlWriter.Create(stringWriter)) xDocument.WriteTo(xmlWriter);

Eso produce el encabezado:

<?xml version="1.0" encoding="utf-16"?>

¿Qué File.WriteAllText si usa File.WriteAllText para escribir su cadena XML en un archivo? Por defecto, tendrías un archivo utf-8 con un encabezado utf-16 .

En tales escenarios, sería más seguro usar StreamWriter , y construirlo con una ruta de archivo, o un FileStream , o si desea examinar los datos, utilice un MemoryStream y obtenga una matriz de bytes . Todas estas combinaciones garantizarían que la codificación en bytes y la generación del encabezado estuvieran guiadas por el mismo valor de Encoding en su StreamWriter .

El objetivo de la propiedad Encoding era permitir que los generadores de secuencias de caracteres incluyeran información precisa sobre la codificación en la secuencia de caracteres en sí (como en el ejemplo XML, otros ejemplos incluyen encabezados de correo electrónico, etc.).

Pero al introducir StringWriter , ese vínculo entre la generación de contenido y la codificación se rompe, por lo que dichos mecanismos automáticos dejan de funcionar y se vuelven potencialmente propensos a errores.

Sin embargo, StringWriter es un adaptador útil si tiene cuidado, es decir, comprende que su código de generación de contenido no debe depender del valor sin sentido de la propiedad de Encoding . Pero ese tipo de advertencia comúnmente se asocia con el patrón del adaptador. A menudo es una especie de truco que te permite colocar una clavija cuadrada casi redonda en un agujero redondo.


Sobre la base de las respuestas (buenas) anteriores, StringWriter es en realidad mucho más versátil que StringBuilder, proporcionando muchas sobrecargas.

Por ejemplo:

Mientras que Stringbuilder solo acepta una cadena o nada para Appendline

StringBuilder sb = new StringBuilder(); sb.AppendLine("A string");

StringWriter puede tomar un formato de cadena directamente

StringWriter sw = new StringWriter(); sw.WriteLine("A formatted string {0}", DateTime.Now);

Con StringBuilder uno debe hacer esto (o usar string.Format, o $ "")

sb.AppendFormat("A formatted string {0}", DateTime.Now); sb.AppendLine();

No hacer o morir cosas, pero aún así una diferencia


Un StringWriter se utiliza para escribir texto en un archivo memoria y un StringBuilder se utiliza para agregar cadenas juntas de una manera eficiente de la memoria.


StringWriter deriva de TextWriter , que permite que varias clases escriban texto sin importar a dónde va. En el caso de StringWriter , la salida solo está en la memoria. TextWriter usar esto si está llamando a una API que necesita un TextWriter pero solo desea generar resultados en la memoria.

StringBuilder es esencialmente un búfer que le permite realizar varias operaciones (generalmente se agrega) a una "cadena lógica" sin crear un nuevo objeto de cadena cada vez. Lo usarías para construir una cadena en múltiples operaciones.


StringBuilder se utiliza para la concatenación masiva de cadenas. Es más efectivo para más de 5 cuerdas, hasta donde sé, entonces String.Concat() . También se puede usar con un formato específico ( .AppendFormat() )


StringBuilder y StringReader se utilizan para mejorar el rendimiento en diferentes situaciones.
Utilice StringBuilder para mejorar el rendimiento en la manipulación de cadenas, como la concatenación, la modificación de cadenas repetidamente.

Random rnd = new Random(); StringBuilder sb = new StringBuilder(); // Generate 10 random numbers and store in sb. for (int i = 0; i < 10; i++) { sb.Append(rnd.Next().ToString("N5")); } Console.WriteLine("The original string:"); Console.WriteLine(sb.ToString()); // Decrease each number by one. for (int ctr = 0; ctr < sb.Length; ctr++) { if (Char.GetUnicodeCategory(sb[ctr]) == System.Globalization.UnicodeCategory.DecimalDigitNumber) { int number = (int)Char.GetNumericValue(sb[ctr]); number--; if (number < 0) number = 9; sb[ctr] = number.ToString()[0]; } } Console.WriteLine("/nThe new string:"); Console.WriteLine(sb.ToString());

Use StringReader para analizar una gran cantidad de texto en líneas separadas y minimizar el uso de memoria mientras procesa datos. Vea el siguiente ejemplo donde el método ReadLine en StringReader simplemente busca la próxima línea nueva comenzando en la posición actual, y luego regresa una cadena basada en la cadena del campo.

using (StringReader sr = new StringReader("input.txt")) { // Loop over the lines in the string or txt file. int count = 0; string line; while((line = sr.ReadLine()) != null) { count++; Console.WriteLine("Line {0}: {1}", count, line); } }