Подтвердить что ты не робот

Есть ли способ в Matlab определить количество строк в файле без прокрутки каждой строки?

Очевидно, можно прокручивать файл с помощью функции fgetl или аналогичной функции и увеличивать счетчик, но есть ли способ определить количество строк в файле без выполнения такого цикла?

4b9b3361

Ответ 1

Мне нравится использовать следующий код для этой задачи

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

Это довольно быстро, если у вас достаточно памяти, чтобы сразу прочитать весь файл. Он должен работать как для окончаний строк в Windows, так и для Linux.

Изменить: Я измерил эффективность ответов, представленных до сих пор. Вот результат для определения количества строк текстового файла, содержащего 1 миллион двойных значений (по одному значению в строке). Среднее 10 попыток.

 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

Настолько быстрыми являются подходы с использованием Perl и чтение всего файла в виде двоичных данных. Я бы не удивился, если бы Perl внутренне также читал большие блоки файла одновременно, а не прокручивал его по строкам (просто догадаться, ничего не знаю о Perl).

Использование простого fgetl() -loop в 25-75 раз медленнее, чем другие подходы.

Редактировать 2: Включенный Edric 2nd approach, который намного быстрее и на уровне с решением Perl, я бы сказал.

Ответ 2

Я думаю, что цикл на самом деле лучший - все остальные варианты до сих пор предлагали либо полагаться на внешние программы (нужно проверить ошибки, нужно str2num, сложнее отлаживать/запускать кросс-платформу и т.д.), либо прочитать весь файл за один присест. Петли не так уж плохи. Здесь мой вариант

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: Джонас справедливо отмечает, что вышеприведенный цикл очень медленный. Здесь более быстрая версия.

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

Это все еще не так быстро, как wc -l, но это тоже не катастрофа.

Ответ 3

Я нашел хороший трюк здесь:

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' - perl script, содержащий

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

Ответ 4

Вы можете прочитать весь файл сразу, а затем подсчитать, сколько строк вы прочитали.

fid = fopen('yourFile.ext');

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

numberOfLines = length(allText{1});

fclose(fid)

Ответ 5

Я бы рекомендовал использовать для этого внешний инструмент. Например, приложение под названием cloc, которое вы можете бесплатно скачать здесь.

В linux вы просто набираете cloc <repository path> и получаете

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

Они также утверждают, что он должен работать над окнами.