25

明らかに、fgetlまたは同様の関数を使用してファイルをループし、カウンターをインクリメントすることもできますが、そのようなループを実行せずにファイルの行数を決定する方法はありますか?

4

5 に答える 5

34

私はまさにこのタスクに次のコードを使用するのが好きです

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万個のdouble値(1行に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がファイルを1行ずつループするのではなく、ファイルの大きなブロックを内部的に一度に読み取る場合でも、驚くことではありません(推測では、Perlについては何も知りません)。

単純なループを使用するfgetl()と、他のアプローチよりも25〜75倍遅くなります。

編集2: Edricの2番目のアプローチが含まれています。これは、Perlソリューションとはるかに高速で、同等です。

于 2012-08-29T11:22:32.707 に答える
16

ループが実際に最善だと思います-これまでに提案された他のすべてのオプションは、外部プログラムに依存するか(エラーチェックが必要、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ありませんが、災害でもありません。

于 2012-08-29T12:00:20.430 に答える
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

ここ'countlines.pl'で、perlスクリプトが含まれています。

while (<>) {};
print $.,"\n";
于 2012-08-29T11:14:52.827 に答える
4

ファイル全体を一度に読み取ってから、読み取った行数を数えることができます。

fid = fopen('yourFile.ext');

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

numberOfLines = length(allText{1});

fclose(fid)
于 2012-08-29T11:15:50.620 に答える
0

これには外部ツールを使用することをお勧めします。たとえば、ここ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
-------------------------------------------------------------------------------

彼らはまたそれが窓で働くべきであると主張します。

于 2016-04-14T08:57:50.740 に答える