2010-07-08 18 views
5

Ho un oggetto Stringbuilder che è stato popolato da un file di testo. Come posso controllare l'oggetto StringBuilder e rimuovere righe "vuote" consecutive.Rimozione di righe vuote consecutive da StringBuilder

cioè

Line 1: This is my text 
Line 2: 
Line 3: Another line after the 1st blank one 
Line 4: 
Line 5: 
Line 6: Next line after 2 blank lines 

(numeri di riga fornita a titolo indicativo)

La riga vuota sulla linea 2 è soddisfacente, ma desidero rimuovere la riga vuota duplicato, sulla linea 5, e così sopra.

Se per argomento la linea 6 sarebbe stata anche una riga vuota e una riga 7 aveva un valore, vorrei che fosse rimossa la riga vuota 5 e la riga vuota 6, in modo che ci fosse solo una riga vuota tra la linea 3 e Linea 7.

Grazie in anticipo.

+0

Basta non aggiungerli() a StringBuilder quando si legge il file. –

+0

Grazie, ma è un altro componente che legge nel file di testo che ha un metodo .GetStringBuilder(). Scusa, ho dimenticato di dirlo. – Riaan

risposta

3

Devi già avere il contenuto del file in un StringBuilder?

Sarebbe più bello poter leggere riga per riga. Qualcosa di simile:

private IEnumerable<string> GetLinesFromFile(string fileName) 
{ 
    using (var streamReader = new StreamReader(fileName)) 
    { 
    string line = null; 
    bool previousLineWasBlank = false; 
    while ((line = streamReader.ReadLine()) != null) 
    { 
     if (!previousLineWasBlank && string.IsNullOrEmpty(line)) 
     { 
     yield return line; 
     } 

     previousLineWasBlank = string.IsNullOrEmpty(line); 
    } 
    } 
} 

Ora si può leggere nel testo (che ha avuto righe vuote babbeo rimosse) in questo modo:

foreach (var line in GetLinesFromFile("myFile.txt")) 
{ 
    Console.WriteLine(line); 
} 

Nota: sto solo illustrando una tecnica qui. Ci sono altre considerazioni: ad es. il mio metodo iteratore mantiene aperto il file mentre gli utenti stanno elaborando il foreach. Questo è bello ed efficiente in termini di memoria (più che leggere in una stringa, ad esempio) poiché si tratta solo di una riga alla volta, ma non è l'ideale per i file che richiedono molto tempo per essere elaborati.

+0

Sì, sarebbe, ma è un altro componente che legge nel file di testo che ha un metodo .GetStringBuilder(). Scusa, ho dimenticato di dirlo. Terrò questo a mente per la lettura di file di testo. – Riaan

+0

+1 per usare la [email protected], ti suggerirei di ignorare/riscrivere l'altro componente. Tra le risposte inserite finora, questa è di gran lunga la più efficiente e lascia aperta la porta per l'utilizzo di buffer per file di grandi dimensioni. L'approccio StringBuilder sarà molto più lento dello streaming. –

+0

@Daniel. Essere d'accordo. – Riaan

2

StringBuilder è molto meno flessibile quando si tratta di cercare da & rimozione. È utilizzato come supporto per accelerare la concatenazione poiché "string" + "another string" è un'operazione molto costosa.

Suggerisco di utilizzare .ToString() quindi Regex.Replace con un'espressione regolare compilata con flag impostati per consentire multiline.

probabilmente si vorrà un modello di ricerca di:

(\n[\w-\n]*\n) 

E sostituirla con la stringa vuota.

Verificare Expresso per un ottimo strumento di espressione regolare .NET.

+0

Ci proverò e grazie per il suggerimento sullo strumento RegEx. – Riaan

3

Probabilmente non molto efficiente, ma è facile.

while(sb.ToString().Contains(Environment.NewLine + Environment.NewLine)) 
{ 
    sb = sb.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); 
} 
+1

"non molto efficiente" è un eufemismo piuttosto grande. –

+1

@Hans: Beh, è ​​tutto relativo, in un recente progetto che ho riscritto, gli sviluppatori precedenti avevano utilizzato l'automazione di Excel per analizzare i file CSV (aprire il file in Excel, copiare le 32.000 prime righe * 12 colonne, cella per cella in un array multidim nell'app C#), ci sono voluti circa 12 minuti per caricare il file di 300 righe in memoria. Quindi, in confronto, non credo che sia troppo brutto :) –

+0

Hmya, * tutto * è relativo a quello che suppongo. –