new - ¿Hay alguna manera en Matlab para determinar el número de líneas en un archivo sin pasar por cada línea?
new line title matlab (5)
Creo que un bucle es de hecho el mejor, todas las demás opciones hasta ahora sugerían confiar en programas externos (necesitan verificar errores, necesitan str2num, son más difíciles de depurar / ejecutar multiplataforma, etc.) o leen todo el archivo de una vez . Los bucles no son tan malos. Aquí está mi variante
function count = countLines(fname)
fh = fopen(fname, ''rt'');
assert(fh ~= -1, ''Could not read: %s'', fname);
x = onCleanup(@() fclose(fh));
count = 0;
while ischar(fgetl(fh))
count = count + 1;
end
end
EDITAR: Jonas señala correctamente que el ciclo anterior es muy lento. Aquí hay una versión más rápida.
function count = countLines(fname)
fh = fopen(fname, ''rt'');
assert(fh ~= -1, ''Could not read: %s'', fname);
x = onCleanup(@() fclose(fh));
count = 0;
while ~feof(fh)
count = count + sum( fread( fh, 16384, ''char'' ) == char(10) );
end
end
Todavía no es tan rápido como wc -l
, pero tampoco es un desastre.
Obviamente, uno podría recorrer un archivo usando fgetl o una función similar e incrementar un contador, pero ¿hay alguna manera de determinar el número de líneas en un archivo sin hacer un bucle?
Encontré un buen truco here :
if (isunix) %# Linux, mac
[status, result] = system( [''wc -l '', ''your_file''] );
numlines = str2num(result);
elseif (ispc) %# Windows
numlines = str2num( perl(''countlines.pl'', ''your_file'') );
else
error(''...'');
end
donde ''countlines.pl''
es una secuencia de comandos perl, que contiene
while (<>) {};
print $.,"/n";
Me gusta usar el siguiente código para exactamente esta tarea
fid = fopen(''someTextFile.txt'', ''rb'');
%# Get file size.
fseek(fid, 0, ''eof'');
fileSize = ftell(fid);
frewind(fid);
%# Read the whole file.
data = fread(fid, fileSize, ''uint8'');
%# Count number of line-feeds and increase by one.
numLines = sum(data == 10) + 1;
fclose(fid);
Es bastante rápido si tiene suficiente memoria para leer todo el archivo a la vez. Debería funcionar para finales de línea de estilo Windows y Linux.
Editar: Medí el rendimiento de las respuestas proporcionadas hasta el momento. Aquí está el resultado para determinar el número de líneas de un archivo de texto que contiene 1 millón de valores dobles (un valor por línea). Promedio de 10 intentos.
Author Mean time +- standard deviation (s)
------------------------------------------------------
Rody Oldenhuis 0.3189 +- 0.0314
Edric (2) 0.3282 +- 0.0248
Mehrwolf 0.4075 +- 0.0178
Jonas 1.0813 +- 0.0665
Edric (1) 26.8825 +- 0.6790
Los más rápidos son los enfoques que usan Perl y la lectura de todo el archivo como datos binarios. No me sorprendería si Perl internamente también leyera grandes bloques del archivo a la vez en lugar de recorrerlo línea por línea (solo una suposición, no sé nada sobre Perl).
Usar un simple fgetl()
-loop es por un factor de 25-75 más lento que los otros enfoques.
Editar 2: incluyó el segundo enfoque de Edric, que es mucho más rápido y a la par con la solución de Perl, diría yo.
Puede leer el archivo completo a la vez y luego contar cuántas líneas ha leído.
fid = fopen(''yourFile.ext'');
allText = textscan(fid,''%s'',''delimiter'',''/n'');
numberOfLines = length(allText{1});
fclose(fid)
Yo recomendaría usar una herramienta externa para esto. Por ejemplo, una aplicación llamada cloc
, que puedes descargar here gratis.
En Linux, simplemente escriba cloc <repository path>
y obtenga
YourPC$ cloc <directory_path>
87 text files.
81 unique files.
23 files ignored.
http://cloc.sourceforge.net v 1.60 T=0.19 s (311.7 files/s, 51946.9 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
MATLAB 59 1009 1074 4993
HTML 1 0 0 23
-------------------------------------------------------------------------------
SUM: 60 1009 1074 5016
-------------------------------------------------------------------------------
También afirman que debería funcionar en Windows.