2009-03-02 14 views

Odpowiedz

2

A StringWriter służy do wpisywania tekstu do pamięć plik i StringBuilder służy do dołączania ciągi razem w sposób pamięci efektywny.

0

StringBuilder służy do łączenia ciągów ciągów. Jest bardziej skuteczny na więcej niż 5 ciągów, o ile wiem, to String.Concat(). Również może być używany z określonym formacie (.AppendFormat())

+0

Twój ostatni akapit dotyczy String * Builder *, a nie StringWriter. –

+1

Hmm .. MSDN powiedział, że "Klasa StringWriter implementuje TextWriter do zapisywania informacji w łańcuchu" http://msdn.microsoft.com/en-us/library/system.io.stringwriter.aspx – abatishchev

3

Klasa StringBuilder jest zasadniczo zmienny łańcuch, klasa pomocnika do konstruktem niezmienna strun. Model StringWriter jest zbudowany na wierzchu, aby dodać więcej wygodnych funkcji do formatowania ciągów.

54

StringWriter wywodzi się z TextWriter, co umożliwia różnym klasom pisanie tekstu bez dbania o to, dokąd zmierza. W przypadku StringWriter wyjście jest właśnie w pamięci. Możesz użyć tego, jeśli wywołujesz interfejs API, który potrzebuje TextWriter, ale chcesz tylko gromadzić wyniki w pamięci.

StringBuilder jest w zasadzie buforem, który pozwala wykonywać wiele operacji (zazwyczaj dołączanych) do "ciągu logicznego" bez tworzenia nowego obiektu ciągów za każdym razem. Możesz użyć tego do skonstruowania łańcucha w wielu operacjach.

69

Nie sądzę, że żadna z istniejących odpowiedzi naprawdę odpowiada na pytanie. Rzeczywisty związek między tymi dwiema klasami to przykład the adaptor pattern.

StringWriter implementuje wszystkie metody Write..., przekazując do instancji StringBuilder, które przechowuje w polu. To nie jest tylko wewnętrzny szczegół, ponieważ StringWriter ma publiczną metodę GetStringBuilder, która zwraca wewnętrzny konstruktor ciągów, a także a constructor, który pozwala na przekazanie istniejącego StringBuilder.

Tak więc StringWriter to adapter, który pozwala na użycie StringBuilder jako celu przez kod, który oczekuje pracy z TextWriter. Jeśli chodzi o podstawowe zachowanie, nie ma między nimi oczywistego wyboru ... chyba, że ​​można zmierzyć koszty przekazywania połączeń, w którym to przypadku StringWriter jest nieco wolniejsze, ale wydaje się to mało prawdopodobne, aby było znaczące.

Dlaczego więc nie stworzyli StringBuilder wdrożenia TextWriter bezpośrednio? Jest to szara strefa, ponieważ intencja interfejsu nie zawsze jest jasna na pierwszy rzut oka.

jest bardzo blisko interfejs do czegoś, co akceptuje strumień znaków. Ale ma dodatkową zmarszczkę: właściwość o nazwie Encoding. Oznacza to, że TextWriter jest interfejsem do czegoś, co akceptuje strumień znaków , a także konwertuje je na bajty.

To jest niepotrzebny ślad w StringWriter, ponieważ nie wykonuje kodowania.documentation mówi:

Ta nieruchomość jest niezbędna dla niektórych scenariuszach XML gdzie nagłówek musi być pisemne zawierające kodowanie używane przez StringWriter. Ten numer pozwala kodowi XML na wykorzystanie dowolnego StringWriter i wygenerowanie poprawnego nagłówka XML w postaci .

Ale to nie może być prawda, bo nie ma dla nas sposób, aby określić wartość Encoding dla StringWriter. Właściwość ma zawsze wartość UnicodeEncoding. W związku z tym każdy kod, który zbadałby tę właściwość do zbudowania nagłówka XML, zawsze powiedziałby: utf-16. Na przykład:

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

która produkuje nagłówek:

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

Co jeśli użyto File.WriteAllText napisać ciąg XML do pliku? Domyślnie będziesz miał plik utf-8 z nagłówkiem utf-16.

W takich sytuacjach byłoby bezpieczniejsze w użyciu StreamWriter i budować go ze ścieżką pliku, lub FileStream, lub jeśli chcesz przeanalizować dane a następnie użyć MemoryStream i tak obtain an array of bytes. Wszystkie te kombinacje zapewniłyby, że kodowanie do bajtów i generowanie nagłówków były prowadzone przez tę samą wartość Encoding w twoim StreamWriter.

Celem właściwości było umożliwienie generatorom strumieni znaków zawarcia dokładnych informacji o kodowaniu w samym strumieniu znaków (np. W przykładzie XML, inne przykłady obejmują nagłówki wiadomości e-mail itp.).

Ale wprowadzając StringWriter, połączenie między generowaniem treści i kodowaniem jest zepsute, a więc takie automatyczne mechanizmy przestają działać i stają się potencjalnie podatne na błędy.

Mimo to, StringWriter jest przydatnym adapterem, jeśli jesteś ostrożny, tzn. Rozumiesz, że twój kod generowania treści nie powinien zależeć od bezsensownej wartości właściwości Encoding. Ale tego rodzaju zastrzeżenie jest zwykle związane z wzorcem adaptera. Często jest to hak pozwalający ci dopasować kwadratowy, ale prawie okrągły kołek do okrągłej dziury.

+0

@SandRock patrz akapit drugi –

3

Bazując na poprzednich (dobrych) odpowiedziach, StringWriter jest w rzeczywistości dużo bardziej wszechstronny niż StringBuilder, zapewniając wiele przeciążeń.

Na przykład:

Podczas StringBuilder akceptuje tylko łańcuch lub nic dla Appendline

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

StringWriter może wziąć format string bezpośrednio

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

Z StringBuilder trzeba to zrobić (lub użyj ciągu.Format lub $ "")

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

NIE or die rzeczy, ale nadal różnica

1

StringBuilder i StringReader służą do poprawy wydajności w różnych sytuacjach.
UżyjStringBuilder, aby poprawić wydajność podczas manipulacji łańcuchami, np. Konkatenacji, wielokrotnego modyfikowania ciągu znaków.

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()); 

ZastosowanieStringReader analizować duże ilości tekstu w osobnej linii i zminimalizowania wykorzystania pamięci podczas przetwarzania danych. Zobacz następny przykład, w którym metoda ReadLine na StringReader po prostu skanuje następny wiersz rozpoczynając od bieżącej pozycji, a następnie zwraca sbstring na podstawie ciągu pola.

+0

Proszę podać wyjaśnienie dla downvoting ... –

+0

ładna odpowiedź .... – Unbreakable

Powiązane problemy