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.
const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(fileName))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize)) {
String line;
while ((line = streamReader.ReadLine()) != null)
// Process line
}
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.
var lines = File.ReadLines(fileName);
foreach (var line in lines)
// Process line
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 nie IEnumerable<String>
pozwala na losowy dostęp do linii.
var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
var line = lines[i];
// Process line
}
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.
using (var streamReader = File.OpenText(fileName)) {
var lines = streamReader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
// Process line
}
Moja sugestia to użycie, File.ReadLines
ponieważ jest czyste i wydajne. Jeśli potrzebujesz specjalnych opcji udostępniania (na przykład używasz FileShare.ReadWrite
), możesz użyć własnego kodu, ale powinieneś zwiększyć rozmiar bufora.
Fastest
ciebie znaczy od wydajności lub rozwojowych perspektyw?