30

unxutils 'を試しましwc -lたが、1GB のファイルでクラッシュしました。このC#コードを試しました

long count = 0;
using (StreamReader r = new StreamReader(f))
{
    string line;
    while ((line = r.ReadLine()) != null)
    {
        count++;
    }
}

return count;

500MB のファイルを 4 秒で読み込みます

var size = 256;
var bytes = new byte[size];
var count = 0;
byte query = Convert.ToByte('\n');
using (var stream = File.OpenRead(file))
{
    int many;
    do
    {
        many = stream.Read(bytes, 0, size);
        count += bytes.Where(a => a == query).Count();                    
    } while (many == size);
}

10 秒で読み取ります

var count = 0;
int query = (int)Convert.ToByte('\n');
using (var stream = File.OpenRead(file))
{
    int current;
    do
    {
        current = stream.ReadByte();
        if (current == query)
        {
            count++;
            continue;
        }
    } while (current!= -1);
}

7秒かかります

まだ試していないより速いものはありますか?

4

6 に答える 6

14

File.ReadLines.NET 4.0 で導入されました

var count = File.ReadLines(file).Count();

最初のコード スニペットと同じ 4 秒で動作します

于 2011-05-23T18:45:29.837 に答える
12

最初のアプローチは、すでに最適なソリューションのように見えます。ほとんどの場合、CPU バウンドではなく、HD の読み取り速度によって制限されることに注意してください。500MB / 4 秒 = 125MB/秒で、すでにかなり高速です。それよりも高速になる唯一の方法は、RAID または SSD を使用することであり、より優れたアルゴリズムを使用する方法はあまりありません。

于 2011-05-23T18:46:33.633 に答える
2

ファイル内の行を効率的にカウントするツールを探しているだけですか? その場合は、MS LogParserを試してください

以下のようなものは、行数を示します。

LogParser "SELECT count(*) FROM file" -i:TEXTLINE
于 2011-05-23T18:49:18.750 に答える
2

本当に速くしたい場合は、C コードを検討してください。

これがコマンド ライン ユーティリティである場合は、CLR または .NET を初期化する必要がないため、高速になります。また、ファイルから読み取る行ごとに新しい文字列を再割り当てしないため、おそらくスループットの時間を節約できます。

1g行のファイルがないので比較できません。ただし、試すことができます:

/*
 * LineCount.c
 *
 * count lines...
 *
 * compile with: 
 *
 *  c:\vc10\bin\cl.exe /O2 -Ic:\vc10\Include -I\winsdk\Include 
 *          LineCount.c -link /debug /SUBSYSTEM:CONSOLE /LIBPATH:c:\vc10\Lib
 *          /LIBPATH:\winsdk\Lib /out:LineCount.exe
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


void Usage(char *appname)
{
    printf("\nLineCount.exe\n");
    printf("  count lines in a text file...\n\n");
    printf("usage:\n");
    printf("  %s <filename>\n\n", appname);
}



int linecnt(char *file)
{
    int sz = 2048;
    char *buf = (char *) malloc(sz);
    FILE *fp = NULL;
    int n= 0;
    errno_t rc = fopen_s(&fp, file, "r");

    if (rc) {
        fprintf(stderr, "%s: fopen(%s) failed: ecode(%d)\n",
                __FILE__, file, rc);
        return -1;
    }

    while (fgets(buf, sz, fp)){
        int r = strlen(buf);
        if (buf[r-1] == '\n')
            n++;
        // could re-alloc here to handle larger lines
    }
    fclose(fp);
    return n;
}

int main(int argc, char **argv)
{
    if (argc==2) {
        int n = linecnt (argv[1]);
        printf("Lines: %d\n", n);
    }
    else {
        Usage(argv[0]);
        exit(1);
    }
}
于 2011-05-23T18:57:55.327 に答える
1

あなたの答えはよさそうだと思います。私が追加する唯一のことは、バッファサイズで遊ぶことです。バッファサイズによってパフォーマンスが変わる可能性があると思います。

バッファ サイズを参照してください -最適なファイル バッファ読み取りサイズ?

于 2011-05-23T18:43:09.920 に答える
1

フレックスは試しましたか?

%{
long num_lines = 0;
%}
%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn

%%
.+ { }
\n { ++num_lines; }
%%
int main(int argc, char **argv);

int main (argc,argv)
int argc;
char **argv;
{
yylex();
printf( "# of lines = %d\n", num_lines );
return 0;
}

次のようにコンパイルするだけです:

flex -Cf scanner.l 
gcc -O -o lineCount.exe scanner.c

stdin で入力を受け入れ、行数を出力します。

于 2011-05-23T18:58:21.930 に答える