2010-08-03 8 views
26

Ho letto recentemente che in StringWriter e StringReader vengono utilizzati per la scrittura e la lettura da StringBuilder.StringBuilder Vs StringWriter/StringReader

Bene, quando utilizzo l'oggetto StringBuilder, sembra essere una classe autosufficiente.

Abbiamo ogni modo di leggere e scrivere il StringBuilder, utilizzando StringBuilder.Append(), Insert(), Replace(), Remove() ecc ...

  1. Qual è il possibile uso di StringWriter e StringReader, che non può essere fatto da StringBuilder si?
  2. Qual è il loro uso pratico?
  3. Quale potrebbe essere la possibile ragione per cui non stanno prendendo in carico Stream come input (Perché qualsiasi altro scrittore e lettore sta prendendo il flusso come parametro di Constructor su cui operare) ma lo StringBuilder?
+1

Possibile duplicato di [StringWriter o StringBuilder] (http://stackoverflow.com/questions/602279/stringwriter-or-stringbuilder) –

risposta

31

Qual è il possibile utilizzo di StringWriter e StringReader, che non può essere eseguito da StringBuilder stesso?

StringReader e StringWriter derivano rispettivamente da TextReader e TextWriter. Pertanto, ciò che possono fare è un'istanza TextReader o TextWriter, che non può essere string o StringBuilder perché non derivano nessuno di questi tipi.

Qual è il loro uso pratico?

Essi consentono di chiamare le API che si aspettano un TextReader o TextWriter, quando quello che hai/desiderare è un string o StringBuilder.

Quale potrebbe essere la possibile ragione per cui non stanno prendendo flusso come ingresso (A causa qualsiasi altro scrittore e il lettore stanno prendendo il flusso come il parametro del costruttore di operare su) ma lo StringBuilder?

Perché non funzionano su flussi; funzionano su string s o StringBuilder s. Sono solo semplici classi wrapper che adattano questi tipi per le API che si aspettano un'interfaccia diversa. Vedi: adapter pattern.

1

Non sono sicuro di chi ti ha detto che il loro scopo era per l'uso con StringBuilder, ma questo è assolutamente scorretto. Come hai notato, StringBuilder può essere letto e scritto senza l'uso di un'altra classe. Le classi StringWriter e StringReader estendono le classi di base TextReader e TextWriter .Net Framework e forniscono funzionalità simili al flusso per lavorare con i dati testuali. Ad esempio, se hai bisogno di lavorare con alcune delle classi di tipo XmlDocument, alcuni metodi ti permettono di caricare i dati Xml tramite un TextReader, quindi se hai il testo Xml come variabile stringa, puoi caricarlo in StringReader e quindi fornirlo a XmlDocument.

+0

Ciao, grazie per la vostra risposta. Sono d'accordo al punto che è derivato da TextWriter/TextReader. Ho preso StringWriter per esempio e ho trovato che entrambe le seguenti inizializzazioni non funzionano. FileStream fs = nuovo FileStream (@ "C: \ Users \ Saravanan \ Documents \ something.bin", FileMode.OpenOrCreate); StringWriter sw1 = File.CreateText (@ "C: \ Users \ Saravanan \ Documents \ something.bin"); StringWriter sw2 = new StringWriter (fs); Ci vuole solo Stringbuilder per scrivere. – SaravananArumugam

+1

@Saravanandss - Se stai cercando di leggere/scrivere da/verso i flussi, quindi utilizzare 'StreamReader' e' StreamWriter' ... ecco a cosa servono. 'StringReader' e' StringWriter' non sono progettati per lavorare con i file; sono progettati per lavorare con le stringhe. Perché stai cercando di usarli? –

5

Altri hanno già detto, ma è perché derivano da TextReader/TextWriter e possono essere utilizzati al posto di essi.Per prima cosa ha più senso usare lo stesso metodo per l'output di linee che si usano per un file se si desidera che il contenuto sia una stringa. Se vuoi un output che si estenda su più righe in memoria, perché preoccuparsi di ricordare di mettere "\ r \ n" alla fine di ogni riga con un StringBuilder? Cosa succede se si desidera eseguire il codice o formattare i dati per un sistema che utilizza solo "\ n" per le interruzioni di riga?

StringBuilder sb = new StringBuilder(); 
// will be invalid on systems that only use \n 
sb.AppendFormat("{0:yyyy-MM-dd HH:mm:ss} - Start\r\n", DateTime.Now); 
// still have to add an extra parameter 
sb.AppendFormat("The current time is {0:yyyy-MM-dd HH:mm:ss}{1}", DateTime.Now, 
    Environment.NewLine); 

StringWriter sw = new StringWriter(); 
// Don't have to worry about it, method name tells you there's a line break 
sw.WriteLine("{0:yyyy-MM-dd HH:mm:ss} - Start", DateTime.Now); 
// no extra parameters 
sw.WriteLine("The current time is {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now); 

dire che si desidera elaborare un file riga per riga, si sarebbe probabilmente utilizzare uno StreamReader invece di caricare l'intero file in uno StringBuilder e la divisione è da caratteri di nuova riga in un array, giusto? Con StringReader puoi usare lo stesso identico metodo (purché richieda un TextReader generico) creando StringReader da una stringa da un TextBox o da un modulo web.

I DataContex Linq2Sql hanno una proprietà Log che è possibile impostare su un TextWriter affinché le query vengano emesse prima di essere eseguite per vedere esattamente cosa viene eseguito. È possibile impostare questo a un TextWriter collegato a un file, ma è possibile allegare un StringWriter e stampare i contenuti nella parte inferiore della pagina Web durante il test ...

1

È possibile utilizzare StringReader per leggere tutti i numeri interi da un stringa.

private static void Main() 
{ 
    var str = @" 
       13 
       13 
       0 6 
       0 5 
       0 1 
       0 2 
       5 3 
       6 4 
       5 4 
       3 4 
       7 8 
       9 10 
       11 12 
       9 11 
       9 12"; 


    using (StandardInput input = new StandardInput(new StringReader(str))) 
    { 
     List<int> integers = new List<int>(); 
     int n; 
     while ((n = input.ReadInt32()) != -1) 
     { 
      integers.Add(n); 
     } 
    } 
} 

StandardInput Classe:

class StandardInput : IDisposable 
{ 
    private readonly TextReader reader; 

    public StandardInput(TextReader reader) 
    { 
     this.reader = reader; 
    } 

    public int ReadInt32() 
    { 
     while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != -1) 
     { 
      reader.Read(); 
     } 
     var builder = new StringBuilder(); 
     while (char.IsDigit((char) reader.Peek())) 
      builder.Append((char) reader.Read()); 

     return builder.Length == 0 ? -1 : int.Parse(builder.ToString()); 
    } 

    public double ReadDouble() 
    { 
     while (!char.IsDigit((char)reader.Peek()) && reader.Peek() != '.' 
                && reader.Peek() != -1) 
     { 
      reader.Read(); 
     } 
     var builder = new StringBuilder(); 
     if (reader.Peek() == '.') 
      builder.Append((char) reader.Read()); 
     while (char.IsDigit((char)reader.Peek())) 
      builder.Append((char)reader.Read()); 
     if (reader.Peek() == '.' && !builder.ToString().Contains(".")) 
     { 
      builder.Append((char)reader.Read()); 
      while (char.IsDigit((char)reader.Peek())) 
       builder.Append((char)reader.Read()); 
     } 
     return builder.Length == 0 ? -1 : double.Parse(builder.ToString()); 
    } 

    public void Dispose() 
    { 
     reader.Dispose(); 
    } 
}