Как быстро считать строки? - PullRequest
30 голосов
/ 23 мая 2011

Я пытался unxutils 'wc -l, но он падал для файлов размером 1 ГБ. Я пробовал этот код C #

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

return count;

Он читает файл размером 500 МБ за 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 секунд

Что-нибудь быстрее, я еще не пробовал?

Ответы [ 6 ]

13 голосов
/ 23 мая 2011

File.ReadLines был представлен в .NET 4.0

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

работает за 4 секунды, то же самое время, что и первый фрагмент кода

12 голосов
/ 23 мая 2011

Ваш первый подход уже выглядит как оптимальное решение.Имейте в виду, что вы в основном не привязаны к процессору, а ограничены скоростью чтения HD, которая при скорости 500 МБ / 4 с = 125 МБ / с уже довольно быстра.Единственный способ добиться большей скорости - использовать RAID или SSD, а не лучший алгоритм.

2 голосов
/ 23 мая 2011

Если вы действительно хотите быстро, рассмотрите код 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);
    }
}
2 голосов
/ 23 мая 2011

Вы просто ищете инструмент для эффективного подсчета строк в файле?Если это так, попробуйте MS LogParser

Что-то вроде ниже даст вам количество строк:

LogParser "SELECT count(*) FROM file" -i:TEXTLINE
1 голос
/ 23 мая 2011

Вы пробовали flex?

%{
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 и выводит количество строк.

1 голос
/ 23 мая 2011

Я думаю, что ваш ответ выглядит хорошо.Единственное, что я хотел бы добавить, это играть с размером буфера.Я чувствую, что это может изменить производительность в зависимости от размера буфера.

Пожалуйста, обратитесь к размеру буфера при - Оптимальный размер чтения файлового буфера?

...