Очевидно, можно прокручивать файл с помощью функции fgetl или аналогичной функции и увеличивать счетчик, но есть ли способ определить количество строк в файле без выполнения такого цикла?
Есть ли способ в Matlab определить количество строк в файле без прокрутки каждой строки?
Ответ 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
-------------------------------------------------------------------------------
Они также утверждают, что он должен работать над окнами.