Chcę czytać plik tekstowy wiersz po wierszu. Chciałem wiedzieć, czy robię to tak skutecznie, jak to możliwe w zakresie .NET C # rzeczy.
Do tej pory próbuję:
var filestream = new System.IO.FileStream(textFilePath,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.ReadWrite);
var file = new System.IO.StreamReader(filestream, System.Text.Encoding.UTF8, true, 128);
while ((lineOfText = file.ReadLine()) != null)
{
//Do something with the lineOfText
}
c#
.net
performance
file-io
text-files
Loren C. Fortner
źródło
źródło
Fastest
ciebie znaczy od wydajności lub rozwojowych perspektyw?filestream = new FileStream
wusing()
oświadczeniu, aby uniknąć możliwych irytujących problemów z zablokowanym uchwytem plikuOdpowiedzi:
Aby znaleźć najszybszy sposób na odczytanie pliku linia po linii, będziesz musiał przeprowadzić testy porównawcze. Zrobiłem kilka małych testów na moim komputerze, ale nie można oczekiwać, że moje wyniki będą miały zastosowanie w twoim środowisku.
Korzystanie ze StreamReader.ReadLine
To jest w zasadzie twoja metoda. Z jakiegoś powodu ustawiłeś rozmiar bufora na najmniejszą możliwą wartość (128). Zwiększenie tego ogólnie zwiększy wydajność. Domyślny rozmiar to 1024, a inne dobre wybory to 512 (rozmiar sektora w systemie Windows) lub 4096 (rozmiar klastra w systemie plików NTFS). Będziesz musiał uruchomić test porównawczy, aby określić optymalny rozmiar bufora. Większy bufor jest - jeśli nie szybszy - przynajmniej nie wolniejszy niż mniejszy bufor.
FileStream
Konstruktor pozwala określić FileOptions . Na przykład, jeśli czytasz duży plik sekwencyjnie od początku do końca, możesz skorzystaćFileOptions.SequentialScan
. Ponownie, analiza porównawcza jest najlepszą rzeczą, jaką możesz zrobić.Korzystanie z File.ReadLines
Jest to bardzo podobne do twojego własnego rozwiązania, z tym wyjątkiem, że jest implementowane przy użyciu
StreamReader
bufora o stałej wielkości 1024. Na moim komputerze powoduje to nieco lepszą wydajność w porównaniu z kodem o rozmiarze bufora 128. Jednak ten sam wzrost wydajności można uzyskać, stosując większy rozmiar bufora. Ta metoda jest implementowana przy użyciu bloku iteratora i nie zużywa pamięci dla wszystkich linii.Korzystanie z File.ReadAllLines
Jest to bardzo podobne do poprzedniej metody, z tą różnicą, że metoda ta powiększa listę ciągów znaków używanych do utworzenia zwróconej tablicy wierszy, więc wymagania dotyczące pamięci są wyższe. Jednak zwraca,
String[]
a nieIEnumerable<String>
pozwala na losowy dostęp do linii.Korzystanie z String.Split
Ta metoda jest znacznie wolniejsza, przynajmniej w przypadku dużych plików (testowanych na pliku 511 KB), prawdopodobnie ze względu na sposób
String.Split
implementacji. Przydziela również tablicę dla wszystkich linii, zwiększając wymaganą pamięć w porównaniu do twojego rozwiązania.Moja sugestia to użycie,
File.ReadLines
ponieważ jest czyste i wydajne. Jeśli potrzebujesz specjalnych opcji udostępniania (na przykład używaszFileShare.ReadWrite
), możesz użyć własnego kodu, ale powinieneś zwiększyć rozmiar bufora.źródło
Jeśli korzystasz z .NET 4, po prostu użyj,
File.ReadLines
który zrobi wszystko za Ciebie. Podejrzewam, że jest bardzo podobny do twojego, z wyjątkiem tego, że może również używaćFileOptions.SequentialScan
i większego bufora (128 wydaje się bardzo mały).źródło
ReadLines()
jest to, że jest leniwy, więc działa dobrze z LINQ.Chociaż
File.ReadAllLines()
jest to jeden z najprostszych sposobów odczytu pliku, jest również jednym z najwolniejszych.Jeśli chcesz tylko czytać wiersze w pliku bez robienia dużo, zgodnie z tymi testami porównawczymi , najszybszym sposobem na odczytanie pliku jest stara metoda:
Jeśli jednak musisz dużo zrobić z każdą linią, w tym artykule stwierdza się, że najlepszym sposobem jest następująca (i szybciej jest wstępnie przydzielić ciąg [], jeśli wiesz, ile linii zamierzasz przeczytać):
źródło
Użyj następującego kodu:
To była OGROMNA różnica w wydajności czytania.
Jest to koszt zużycia pamięci, ale całkowicie warto!
źródło
File.ReadAllLines
Dobry temat na ten temat znajduje się w pytaniu o przepełnienie stosu. Czy zwrot z inwestycji jest wolniejszy niż powrót ze starej szkoły? .
To mówi:
źródło
Jeśli rozmiar pliku nie jest duży, szybciej jest odczytać cały plik i podzielić go później
źródło
File.ReadAllLines()
File.ReadAllLines
mają stały rozmiar bufora, ponieważ rozmiar pliku jest znany.File.ReadAllLines
tworzy listę i dodaje ją do pętli za pomocąStreamReader.ReadLine
(z potencjalnym przeniesieniem podstawowej tablicy). Ta metoda wykorzystuje domyślny rozmiar bufora 1024.StreamReader.ReadToEnd
Pozwala to uniknąć części parsowania linii, a rozmiar bufora można ustawić w konstruktorze, jeśli jest to pożądane.Jeśli masz wystarczającą ilość pamięci, zauważyłem pewien wzrost wydajności, wczytując cały plik do strumienia pamięci , a następnie otwierając czytnik strumieni, aby odczytać wiersze. Tak długo, jak faktycznie planujesz odczytać cały plik, może to przynieść pewne ulepszenia.
źródło
File.ReadAllLines
wydaje się wtedy lepszym wyborem.Nie możesz dostać się szybciej, jeśli chcesz użyć istniejącego API do odczytu linii. Ale czytanie większych fragmentów i ręczne znajdowanie każdej nowej linii w buforze odczytu prawdopodobnie byłoby szybsze.
źródło