【问题标题】:Is there a way in Matlab to determine the number of lines in a file without looping through each line?Matlab中有没有一种方法可以确定文件中的行数而无需遍历每一行?
【发布时间】:2012-08-29 11:06:22
【问题描述】:

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

【问题讨论】:

标签: matlab file-io line-count


【解决方案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 风格的行尾。

编辑:我测量了迄今为止提供的答案的表现。这是确定包含 100 万个双精度值(每行一个值)的文本文件的行数的结果。平均 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 的第二种方法,我会说,它快得多并且与 Perl 解决方案相当。

【讨论】:

  • 谢谢!虽然都是很好的答案,但我选择 Mehrwolf 的作为接受的答案,因为他比较了所有其他答案。我可能实际上会使用 Edric 的第二个答案,因为我更喜欢将所有内容都保存在 Matlab 中。
  • 需要注意的是,如果最后一行没有以\n 结束,Edric (2) 会减一。例如,countLines('countLines.m') 在文件中有 9 行时返回 8。虽然在大多数情况下您的增加 1 说明了这一点,但当最后一行为空白时,它返回的结果与系统命令不一致(至少在 Windows 上,无法测试 Linux)。有关这两种情况的 MCVE,请参阅 this gist
【解决方案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

编辑:乔纳斯正确地指出上述循环真的很慢。这是一个更快的版本。

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那么快,但也不是灾难。

【讨论】:

  • 循环的问题是每次迭代都需要访问文件。在 Matlab 中文件访问速度是出了名的慢;在一个循环中多次这样做会很痛苦。
  • 需要注意的是,如果最后一行没有以\n 结束,则第二种方法将被关闭。例如,countLines('countLines.m') 在文件中有 9 行时返回 8。
  • 查看 this gist 以获得 MCVE
【解决方案3】:

我发现了一个不错的技巧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

'countlines.pl' 是一个 perl 脚本,包含

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

【讨论】:

  • system( ['wc -l ', 'your_file'] ) 也会将文件名输出到result。这可以通过使用system( ['wc -l &lt;', 'your_file'] ) 来避免。
【解决方案4】:

您可以一次读取整个文件,然后计算您已阅读的行数。

fid = fopen('yourFile.ext');

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

numberOfLines = length(allText{1});

fclose(fid)

【讨论】:

  • 这可能会给大文件带来内存问题,因为allText 必须在文件中包含所有文本
  • @RodyOldenhuis:是的,内存肯定是个问题。您的 Perl 解决方案需要多少内存?它是逐行、逐行读取还是全部读取文件?
【解决方案5】:

我建议为此使用外部工具。例如一个名为cloc的应用程序,您可以免费下载here

在 linux 上,您只需输入 cloc &lt;repository path&gt; 并获取

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

他们还声称它应该在 Windows 上工作。

【讨论】:

    猜你喜欢
    • 2018-07-07
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2017-09-20
    • 2020-02-02
    • 1970-01-01
    • 2020-12-01
    • 2013-01-09
    相关资源
    最近更新 更多