c# - para - ¿Cómo contar líneas rápido?
herramienta para contar lineas de codigo (6)
unxutils '' wc -l
pero se estrelló para archivos de 1GB. Probé este código C #
long count = 0;
using (StreamReader r = new StreamReader(f))
{
string line;
while ((line = r.ReadLine()) != null)
{
count++;
}
}
return count;
Lee un archivo de 500MB en 4 segundos.
var size = 256;
var bytes = new byte[size];
var count = 0;
byte query = Convert.ToByte(''/n'');
using (var stream = File.OpenRead(file))
{
int many;
do
{
many = stream.Read(bytes, 0, size);
count += bytes.Where(a => a == query).Count();
} while (many == size);
}
Lee en 10 segundos
var count = 0;
int query = (int)Convert.ToByte(''/n'');
using (var stream = File.OpenRead(file))
{
int current;
do
{
current = stream.ReadByte();
if (current == query)
{
count++;
continue;
}
} while (current!= -1);
}
Toma 7 segundos
¿Hay algo más rápido que no haya probado todavía?
¿Está buscando una herramienta para contar líneas en un archivo de manera eficiente? Si es así, intente MS LogParser
Algo como a continuación te dará varias líneas:
LogParser "SELECT count(*) FROM file" -i:TEXTLINE
¿Has probado flex?
%{
long num_lines = 0;
%}
%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn
%%
.+ { }
/n { ++num_lines; }
%%
int main(int argc, char **argv);
int main (argc,argv)
int argc;
char **argv;
{
yylex();
printf( "# of lines = %d/n", num_lines );
return 0;
}
Solo compila con:
flex -Cf scanner.l
gcc -O -o lineCount.exe scanner.c
Acepta entrada en stdin y genera el número de líneas.
Creo que tu respuesta se ve bien. Lo único que añadiría es jugar con el tamaño del búfer. Siento que puede cambiar el rendimiento dependiendo de su tamaño de búfer.
Consulte el tamaño del búfer en - ¿ Tamaño óptimo de lectura del búfer de archivo?
Si realmente quieres rápido, considera el código C.
Si se trata de una utilidad de línea de comandos, será más rápida porque no tendrá que inicializar CLR o .NET. Y, no reasignará una nueva cadena para cada línea leída del archivo, lo que probablemente ahorra tiempo en el rendimiento.
No tengo ningún archivo con 1g líneas, por lo que no puedo comparar. aunque puedes intentarlo:
/*
* LineCount.c
*
* count lines...
*
* compile with:
*
* c:/vc10/bin/cl.exe /O2 -Ic:/vc10/Include -I/winsdk/Include
* LineCount.c -link /debug /SUBSYSTEM:CONSOLE /LIBPATH:c:/vc10/Lib
* /LIBPATH:/winsdk/Lib /out:LineCount.exe
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Usage(char *appname)
{
printf("/nLineCount.exe/n");
printf(" count lines in a text file.../n/n");
printf("usage:/n");
printf(" %s <filename>/n/n", appname);
}
int linecnt(char *file)
{
int sz = 2048;
char *buf = (char *) malloc(sz);
FILE *fp = NULL;
int n= 0;
errno_t rc = fopen_s(&fp, file, "r");
if (rc) {
fprintf(stderr, "%s: fopen(%s) failed: ecode(%d)/n",
__FILE__, file, rc);
return -1;
}
while (fgets(buf, sz, fp)){
int r = strlen(buf);
if (buf[r-1] == ''/n'')
n++;
// could re-alloc here to handle larger lines
}
fclose(fp);
return n;
}
int main(int argc, char **argv)
{
if (argc==2) {
int n = linecnt (argv[1]);
printf("Lines: %d/n", n);
}
else {
Usage(argv[0]);
exit(1);
}
}
Su primer enfoque ya parece la solución óptima. Tenga en cuenta que, en su mayoría, no está limitado por la CPU, sino que está limitado por la velocidad de lectura del HD, que a 500MB / 4sec = 125MB / s ya es bastante rápido. La única forma de llegar más rápido que eso es a través de RAID o el uso de SSD, no tanto a través de un mejor algoritmo.
File.ReadLines
fue introducido en .NET 4.0
var count = File.ReadLines(file).Count();
Funciona en 4 segundos, al mismo tiempo que el primer fragmento de código.