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 alcance de las cosas .NET C #.
Esto es lo que estoy intentando 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
}
c#
.net
performance
file-io
text-files
Loren C Fortner
fuente
fuente
Fastest
Quieres decir desde las perspectivas de desempeño o desarrollo?filestream = new FileStream
enusing()
la declaración para evitar posibles problemas molestos con mango de archivo bloqueadoRespuestas:
Para encontrar la forma más rápida de leer un archivo línea por línea, tendrá que hacer algunos puntos de referencia. He realizado algunas pequeñas pruebas 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.
El
FileStream
constructor le permite especificar FileOptions . Por ejemplo, si está leyendo un archivo grande secuencialmente de principio a fin, puede beneficiarseFileOptions.SequentialScan
. Una vez más, la evaluación comparativa es lo mejor que puede hacer.Usando File.ReadLines
Esto es muy parecido a su propia solución, excepto que se implementa utilizando un
StreamReader
tamaño de búfer fijo de 1.024. En mi computadora, esto resulta 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 utilizando un bloque iterador y no consume memoria para todas las líneas.Usando File.ReadAllLines
Esto es muy similar al método anterior, excepto que este método hace crecer una lista de cadenas utilizadas para crear la matriz de líneas devuelta, por lo que los requisitos de memoria son mayores. Sin embargo, vuelve
String[]
y no leIEnumerable<String>
permite acceder aleatoriamente a las líneas.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
String.Split
se implementa. También asigna una matriz para todas las líneas aumentando la memoria requerida en comparación con su solución.Mi sugerencia es usar
File.ReadLines
porque es limpio y eficiente. Si necesita opciones especiales para compartir (por ejemplo, las que usaFileShare.ReadWrite
), puede usar su propio código, pero debe aumentar el tamaño del búfer.fuente
Si está utilizando .NET 4, simplemente use
File.ReadLines
cuál lo hace todo por usted. Sospecho que es muy similar al tuyo, excepto que también puede usarFileOptions.SequentialScan
y un búfer más grande (128 parece muy pequeño).fuente
ReadLines()
es que es perezoso, por lo que funciona bien con LINQ.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:
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):
fuente
Utiliza el siguiente código:
Esta fue una gran diferencia en el rendimiento de lectura.
Viene a costa del consumo de memoria, ¡pero vale la pena!
fuente
File.ReadAllLines
Hay un buen tema sobre esto en la pregunta de desbordamiento de pila. ¿ Es más lento el "rendimiento de rendimiento" que el rendimiento de la "vieja escuela"? .
Dice:
fuente
Si el tamaño del archivo no es grande, entonces es más rápido leer todo el archivo y luego dividirlo
fuente
File.ReadAllLines()
File.ReadAllLines
tenga un tamaño de búfer fijo ya que se conoce el tamaño del archivo.File.ReadAllLines
crea una lista y se agrega a esta lista en un bucle usandoStreamReader.ReadLine
(con una posible reasignación de la matriz subyacente). Este método utiliza un tamaño de búfer predeterminado de 1024.StreamReader.ReadToEnd
Evita la parte de análisis de línea y el tamaño del búfer se puede establecer en el constructor si lo desea.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 secuencia para leer las líneas. Siempre y cuando planee leer todo el archivo de todos modos, esto puede producir algunas mejoras.
fuente
File.ReadAllLines
Parece ser una mejor opción entonces.No puede ser más rápido si desea utilizar una API existente para leer las líneas. Pero leer fragmentos más grandes y encontrar manualmente cada nueva línea en el búfer de lectura probablemente sería más rápido.
fuente