txt texto por net linea leer jalar escribir documento contenido como caracter archivo c# .net performance file-io text-files

texto - leer linea por linea de un txt en c#



¿Cuál es la forma más rápida de leer un archivo de texto línea por línea? (9)

Quiero leer un archivo de texto línea por línea. Quería saber si lo estoy haciendo de la manera más eficiente posible dentro del ámbito de las cosas de .NET C #.

Esto es lo que estoy tratando hasta ahora:

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 }


Hay un buen tema sobre esto en la pregunta de desbordamiento de pila ¿ Es el ''rendimiento de rendimiento'' más lento que el de la ''vieja escuela''? .

Dice:

ReadAllLines carga todas las líneas en la memoria y devuelve una cadena []. Todo muy bien si el archivo es pequeño. Si el archivo es más grande de lo que cabe en la memoria, se quedará sin memoria.

ReadLines, por otro lado, usa el rendimiento de rendimiento para devolver una línea a la vez. Con él, puedes leer cualquier archivo de tamaño. No carga todo el archivo en la memoria.

Supongamos que desea encontrar la primera línea que contiene la palabra "foo" y luego salir. Al usar ReadAllLines, tendrías que leer todo el archivo en la memoria, incluso si "foo" aparece en la primera línea. Con ReadLines, solo lees una línea. ¿Cuál sería más rápido?


No puede obtener nada más rápido si desea utilizar una API existente para leer las líneas. Pero la lectura de fragmentos más grandes y la búsqueda manual de cada nueva línea en el búfer de lectura probablemente sería más rápida.


Para encontrar la forma más rápida de leer un archivo línea por línea, tendrá que hacer algunas evaluaciones comparativas. He realizado algunas pruebas pequeñas en mi computadora, pero no puede esperar que mis resultados se apliquen a su entorno.

Usando StreamReader.ReadLine

Este es básicamente tu método. Por alguna razón, establece el tamaño del búfer en el valor más pequeño posible (128). Aumentar esto en general aumentará el rendimiento. El tamaño predeterminado es 1.024 y otras buenas opciones son 512 (el tamaño del sector en Windows) o 4.096 (el tamaño del clúster en NTFS). Tendrá que ejecutar un punto de referencia para determinar un tamaño de búfer óptimo. Un búfer más grande es, si no más rápido, al menos no más lento que un búfer más pequeño.

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 }

El constructor de FileStream permite especificar FileOptions . Por ejemplo, si está leyendo un archivo grande de manera secuencial de principio a fin, puede beneficiarse de FileOptions.SequentialScan . Una vez más, la evaluación comparativa es lo mejor que puedes hacer.

Usando File.ReadLines

Esto se parece mucho a su propia solución, excepto que se implementa utilizando un StreamReader con un tamaño de búfer fijo de 1.024. En mi computadora, esto se traduce en un rendimiento ligeramente mejor en comparación con su código con un tamaño de búfer de 128. Sin embargo, puede obtener el mismo aumento de rendimiento utilizando un tamaño de búfer más grande. Este método se implementa mediante un bloque de iteradores y no consume memoria para todas las líneas.

var lines = File.ReadLines(fileName); foreach (var line in lines) // Process line

Usando File.ReadAllLines

Esto es muy parecido al método anterior, excepto que este método hace crecer una lista de cadenas utilizadas para crear la matriz de líneas devueltas, por lo que los requisitos de memoria son mayores. Sin embargo, devuelve String[] y no una IEnumerable<String> que le permite acceder aleatoriamente a las líneas.

var lines = File.ReadAllLines(fileName); for (var i = 0; i < lines.Length; i += 1) { var line = lines[i]; // Process line }

Usando String.Split

Este método es considerablemente más lento, al menos en archivos grandes (probado en un archivo de 511 KB), probablemente debido a cómo se implementa String.Split . También asigna una matriz para todas las líneas, lo que aumenta la memoria requerida en comparación con su solución.

using (var streamReader = File.OpenText(fileName)) { var lines = streamReader.ReadToEnd().Split("/r/n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) // Process line }

Mi sugerencia es usar File.ReadLines porque es limpio y eficiente. Si necesita opciones especiales para compartir (por ejemplo, utiliza FileShare.ReadWrite ), puede usar su propio código, pero debe aumentar el tamaño del búfer.


Si apuntas a la velocidad de ejecución, sí lo eres. El código podría ser más corto utilizando el constructor StreamReader.


Si bien File.ReadAllLines() es una de las formas más simples de leer un archivo, también es una de las más lentas.

Si solo desea leer líneas en un archivo sin hacer mucho, de acuerdo con estos puntos de referencia , la forma más rápida de leer un archivo es el método antiguo de:

using (StreamReader sr = File.OpenText(fileName)) { string s = String.Empty; while ((s = sr.ReadLine()) != null) { //do minimal amount of work here } }

Sin embargo, si tiene que hacer mucho con cada línea, este artículo concluye que la mejor manera es la siguiente (y es más rápido preasignar una cadena [] si sabe cuántas líneas va a leer):

AllLines = new string[MAX]; //only allocate memory here using (StreamReader sr = File.OpenText(fileName)) { int x = 0; while (!sr.EndOfStream) { AllLines[x] = sr.ReadLine(); x += 1; } } //Finished. Close the file //Now parallel process each line in the file Parallel.For(0, AllLines.Length, x => { DoYourStuff(AllLines[x]); //do your work here });


Si el tamaño del archivo no es grande, es más rápido leer todo el archivo y luego dividir la cadena:

var filestreams = sr.ReadToEnd().Split("/r/n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);


Si está utilizando .NET 4, simplemente use File.ReadLines que lo hace todo por usted. Sospecho que es muy similar al suyo, excepto que también puede usar FileOptions y un búfer más grande (128 parece muy pequeño).


Si tiene suficiente memoria, he encontrado algunas mejoras de rendimiento al leer todo el archivo en una secuencia de memoria y luego abrir un lector de secuencias para leer las líneas. Siempre que planee leer el archivo completo de todos modos, esto puede producir algunas mejoras.


Usa el siguiente código:

var lines = File.ReadAllLines(fileName); foreach (var line in lines)

Esta fue una gran diferencia en el rendimiento de lectura.

Viene a costa del consumo de memoria, ¡pero vale la pena!