2008-09-23 19 views

Respuesta

318

edición serio tardía: Si está utilizando .NET 4.0 o posterior

La clase File tiene un nuevo método, que perezosamente ReadLines enumera las líneas en lugar de leer con avidez a todos ellos en una matriz como ReadAllLines. Así que ahora usted puede tener tanto la eficiencia como la concisión con:

var lineCount = File.ReadLines(@"C:\file.txt").Count(); 

respuesta original

Si usted no está demasiado molesta acerca de la eficiencia, simplemente hay que escribir:

var lineCount = File.ReadAllLines(@"C:\file.txt").Length; 

Para un método más eficiente que podría hacer:

var lineCount = 0; 
using (var reader = File.OpenText(@"C:\file.txt")) 
{ 
    while (reader.ReadLine() != null) 
    { 
     lineCount++; 
    } 
} 

Editar: En respuesta a las preguntas sobre la eficiencia

La razón por la que dijo que el segundo fue más eficiente en cuanto fue el uso de memoria, no necesariamente la velocidad. El primero carga todo el contenido del archivo en una matriz, lo que significa que debe asignar al menos tanta memoria como el tamaño del archivo. El segundo simplemente enlaza una línea a la vez para que nunca tenga que asignar más de una línea de memoria a la vez. Esto no es tan importante para archivos pequeños, pero para archivos más grandes podría ser un problema (si intenta encontrar la cantidad de líneas en un archivo de 4 GB en un sistema de 32 bits, por ejemplo, donde simplemente no es suficiente espacio de direcciones en modo de usuario para asignar una matriz así de grande).

En términos de velocidad, no esperaría que hubiera mucho en ello. Es posible que ReadAllLines tenga algunas optimizaciones internas, pero, por otro lado, puede que tenga que asignar un gran trozo de memoria. Supongo que ReadAllLines podría ser más rápido para archivos pequeños, pero significativamente más lento para archivos grandes; aunque la única forma de saberlo sería medirlo con un cronómetro o un generador de perfiles de código.

+0

¿Por qué el segundo método es menos eficiente que el primero? No es evidente desde el código. – Sklivvz

+0

Mi intuición sería la primera puede ser más rápida, pero eso es solo una suposición – johnc

+2

Nota pequeña: como String es un tipo de referencia, la matriz sería del tamaño de la cantidad de líneas x del tamaño de un puntero, pero está en lo cierto que aún necesita almacenar el texto, cada línea como un único objeto String. –

2

Puede leerlo rápidamente e incrementar un contador, solo use un bucle para incrementar, sin hacer nada con el texto.

+1

Esto debería ser un comentario, no una respuesta. – IamBatman

13

La forma más fácil:

int lines = File.ReadAllLines("myfile").Length; 
1

contar las vueltas de carro/saltos de línea. Creo que en Unicode todavía son 0x000D y 0x000A respectivamente. de esa manera usted puede ser tan eficiente o tan ineficiente como quiera, y decidir si tiene que tratar con ambos caracteres o no

5

Si con facilidad quiere decir líneas de código que son fáciles de descifrar pero que son ineficaces por azar

string[] lines = System.IO.File.RealAllLines($filename); 
int cnt = lines.Count(); 

Esa es probablemente la forma más rápida de saber cuántas líneas.

También podría hacer (dependiendo de si está en buffering)

#for large files 
while (...reads into buffer){ 
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine); 
} 

Hay otras muchas maneras, pero una de las anteriores es probablemente lo que va a ir con.

+3

Yo argumento que este método es muy ineficiente; porque, estás leyendo todo el archivo en la memoria, y en una matriz de cadenas, nada menos. No es necesario copiar el búfer al utilizar ReadLine. Vea la respuesta de @GregBeech. Perdón por llover en tu desfile. –

8

Esto sería usar menos memoria, pero probablemente necesitará más tiempo

int count = 0; 
string line; 
TextReader reader = new StreamReader("file.txt"); 
while ((line = reader.ReadLine()) != null) 
{ 
    count++; 
} 
reader.Close(); 
-1

Puede lanzar el ejecutable ".exe wc" (viene con UnixUtils y no necesita instalación) se ejecute como un proceso externo. Es compatible con diferentes métodos de recuento de líneas (como Unix vs Mac vs Windows).

+0

No hay forma de que esto sea lo suficientemente rápido como para ser útil. La sobrecarga de simplemente llamar al ejecutable sería el doble (la obvia exageración es obvia) como un solo bucle de incremento. – Krythic

0
try { 
    string path = args[0]; 
    FileStream fh = new FileStream(path, FileMode.Open, FileAccess.Read); 
    int i; 
    string s = ""; 
    while ((i = fh.ReadByte()) != -1) 
     s = s + (char)i; 

    //its for reading number of paragraphs 
    int count = 0; 
    for (int j = 0; j < s.Length - 1; j++) { 
      if (s.Substring(j, 1) == "\n") 
       count++; 
    } 

    Console.WriteLine("The total searches were :" + count); 

    fh.Close(); 

} catch(Exception ex) { 
    Console.WriteLine(ex.Message); 
}   
+3

-1: ¡esto será LENTO, consumirá mucha memoria y le dará al GC un tiempo difícil! – ya23

+0

¡esto será LENTO, consumirá mucha memoria y le dará al GC un tiempo difícil! – Professor

0

Una opción viable, y una que he utilizado personalmente, sería agregar su propio encabezado a la primera línea del archivo. Hice esto para un formato de modelo personalizado para mi juego. Básicamente, tengo una herramienta que optimiza mis archivos .obj, eliminando la basura que no necesito, los convierte a un mejor diseño y luego escribe el número total de líneas, caras, normales, vértices y texturas UV en la primera línea Luego, los datos son utilizados por varios buffers cuando se carga el modelo.

Esto también es útil porque solo necesita recorrer el archivo una vez para cargarlo, en lugar de una vez para contar las líneas, y nuevamente para leer los datos en los almacenamientos intermedios creados.

Cuestiones relacionadas