web-dev-qa-db-fra.com

Existe-t-il un moyen dans Matlab de déterminer le nombre de lignes d'un fichier sans passer en boucle d'une ligne à l'autre?

Évidemment, on peut parcourir un fichier en utilisant fgetl ou une fonction similaire et incrémenter un compteur, mais existe-t-il un moyen de déterminer le nombre de lignes dans un fichier sans faire une telle boucle?

23
robguinness

J'aime utiliser le code suivant pour exactement cette tâche

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);

C'est assez rapide si vous avez assez de mémoire pour lire tout le fichier à la fois. Cela devrait fonctionner pour les fins de ligne de style Windows et Linux.

Edit: J'ai mesuré la performance des réponses fournies jusqu'à présent. Voici le résultat pour déterminer le nombre de lignes d'un fichier texte contenant 1 million de valeurs doubles (une valeur par ligne). Moyenne de 10 essais.

 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

Ainsi, les approches les plus rapides utilisant Perl et lisant tout le fichier sous forme de données binaires. Je ne serais pas surpris si Perl lisait également en interne de grands blocs du fichier au lieu de le parcourir en boucle ligne par ligne (devinez, ne savez rien de Perl).

L'utilisation d'une boucle fgetl()- simple est 25 fois plus lente que les autres approches.

Edit 2: Inclut la 2ème approche d'Edric, qui est beaucoup plus rapide et à égalité avec la solution Perl, je dirais.

30
Mehrwolf

Je pense qu'une boucle est en fait la meilleure - toutes les autres options suggérées jusqu'à présent reposent soit sur des programmes externes (besoin de vérifier les erreurs; besoin de str2num; plus difficile de déboguer/exécuter multiplate-forme, etc.) ou de lire le fichier entier en une fois. . Les boucles ne sont pas si mauvaises. Voici ma 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

EDIT: Jonas souligne à juste titre que la boucle ci-dessus est vraiment lente. Voici une version plus rapide.

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

Ce n'est toujours pas aussi rapide que wc -l, mais ce n'est pas un désastre non plus.

15
Edric

J'ai trouvé un bon tour ici :

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

'countlines.pl' est un script Perl contenant

while (<>) {};
print $.,"\n";
12
Rody Oldenhuis

Vous pouvez lire le fichier entier en une fois, puis compter le nombre de lignes que vous avez lues.

fid = fopen('yourFile.ext');

allText = textscan(fid,'%s','delimiter','\n');

numberOfLines = length(allText{1});

fclose(fid)
4
Jonas

Je recommanderais d'utiliser un outil externe pour cela. Par exemple, une application appelée cloc, que vous pouvez télécharger ici gratuitement.

Sur linux, vous tapez simplement cloc <repository path> et vous obtenez

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
-------------------------------------------------------------------------------

Ils prétendent également que cela devrait fonctionner sur les fenêtres.

0
Ufos