2010-07-08 15 views
5

Mam obiekt Stringbuilder, który został wypełniony z pliku tekstowego. Jak mogę sprawdzić obiekt StringBuilder i usunąć kolejne "puste" linie.Usuwanie kolejnych pustych wierszy z StringBuilder

tj

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 

(numery linii podane jako odniesienie tylko)

pustej linii na linii 2 jest w porządku, ale chciałbym, aby usunąć duplikaty pustą linię, na linii 5, a więc na.

Jeśli dla argumentu sake wiersz 6 byłby również pustym wierszem, a wiersz 7 miałby wartość, chciałbym, aby usunięto Blank Line 5 i Blank Line 6, tak aby była tylko jedna pusta linia między linią 3 i linia 7.

Z góry dziękuję.

+0

Po prostu nie dołączaj() do StringBuilder podczas czytania pliku. –

+0

Dzięki, ale jest to kolejny składnik, który czyta w pliku tekstowym, który ma metodę .GetStringBuilder(). Przepraszam, zapomniałem o tym wspomnieć. – Riaan

Odpowiedz

3

Czy musisz już mieć zawartość pliku w StringBuilder?

Byłoby fajniej móc czytać wiersz po wierszu. Coś jak:

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

Teraz można przeczytać w tekście (który miał dupe puste linie usunięte) tak:

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

Uwaga: Ja tylko ilustrujący technikę tutaj. Istnieją inne kwestie: np. moja metoda iteratora utrzymuje plik otwarty, podczas gdy konsumenci przetwarzają foreach. Jest to miłe i wydajne pod względem pamięci (bardziej niż czytanie w łańcuchu znaków), ponieważ masz do czynienia tylko z jedną linią naraz, ale nie jest ona idealna dla plików, których przetwarzanie zajmuje dużo czasu.

+0

Tak, byłby, ale jest innym komponentem, który czyta w pliku tekstowym, który ma metodę .GetStringBuilder(). Przepraszam, zapomniałem o tym wspomnieć. Będę o tym pamiętał podczas czytania w plikach tekstowych. – Riaan

+0

+1 Za wykorzystanie wydajnoś[email protected], sugerowałbym, abyś zignorował/przepisał drugi komponent. Spośród dotychczasowych odpowiedzi, ta jest zdecydowanie najbardziej wydajna i pozostawia otwarte drzwi do używania buforów dla większych plików. Podejście StringBuilder będzie działać znacznie wolniej niż strumieniowanie. –

+0

@ Daniel. Zgodzić się. – Riaan

2

StringBuilder jest dużo mniej elastyczny, jeśli chodzi o wyszukiwanie & usuwanie z. Jest używany jako pomocnik do przyspieszenia konkatenacji, ponieważ "string" + "another string" jest bardzo kosztowną operacją.

Proponuję użyć .ToString() następnie Regex.Replace ze skompilowanym wyrażeniem regularnym z ustawionymi flagami, aby umożliwić multilinię.

prawdopodobnie będziesz chciał wzór wyszukiwarkę:

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

I zastąpić go z pustym ciągiem.

Zapoznaj się z Expresso, aby uzyskać doskonałe narzędzie do wyrażania regularnego .NET.

+0

Spróbuję, a dzięki za napiwek narzędzia RegEx. – Riaan

3

Prawdopodobnie niezbyt wydajna, ale łatwa.

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

"Niezbyt wydajne" jest raczej dużym niedopowiedzeniem. –

+1

@Hans: Cóż, wszystko jest względne, w ostatnim projekcie, który przepisałem, poprzedni deweloperzy użyli automatyzacji Excela do parsowania plików csv (otwórz plik w Excelu, skopiuj 32 000 pierwszych wierszy * 12 kolumn, komórka po komórce do tablica wielodomenowa w aplikacji C#), zajęło około 12 minut załadowanie do pliku średniej 300 linii. Tak więc nie uważam, że to zbyt źle :) –

+0

Hmya, * wszystko * jest w stosunku do tego przypuszczam. –