Matlab中有没有办法确定文件中的行数而不循环遍历每一行?

rob*_*ess 24 file-io matlab line-count

显然,可以使用fgetl或类似函数循环遍历文件并递增计数器,但有没有办法确定文件中的行数而不进行这样的循环?

Meh*_*olf 31

我喜欢使用以下代码来完成此任务

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);
Run Code Online (Sandbox Code Playgroud)

如果你有足够的内存来一次读取整个文件,它会非常快.它应该适用于Windows和Linux风格的行结尾.

编辑:我测量了目前为止提供的答案的表现.以下是确定包含100万个double值(每行一个值)的文本文件的行数的结果.平均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
Run Code Online (Sandbox Code Playgroud)

使用Perl并将所有文件作为二进制数据读取的方法最快.我不会感到惊讶,如果Perl内部也同时读取文件的大块而不是逐行循环(只是一个猜测,对Perl一无所知).

使用简单fgetl()循环比其他方法慢25-75倍.

编辑2:包括Edric的第二种方法,它 Perl解决方案快得多,我会说.


Edr*_*ric 15

我认为循环实际上是最好的 - 到目前为止所有其他选项建议要么依赖外部程序(需要错误检查;需要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
Run Code Online (Sandbox Code Playgroud)

编辑:Jonas正确地指出上述循环非常慢.这是一个更快的版本.

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
Run Code Online (Sandbox Code Playgroud)

它仍然没有那么快wc -l,但它也不是灾难.


Rod*_*uis 12

我发现了一个很不错的技巧在这里:

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
Run Code Online (Sandbox Code Playgroud)

哪里'countlines.pl'是perl脚本,包含

while (<>) {};
print $.,"\n";
Run Code Online (Sandbox Code Playgroud)

  • `system(['wc -l','your_file'])`也会将文件名输出到`result`.使用`system(['wc -l <​​','your_file'])`可以避免这种情况. (2认同)