Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何快速数线?_C#_Streamreader_Wc - Fatal编程技术网

C# 如何快速数线?

C# 如何快速数线?,c#,streamreader,wc,C#,Streamreader,Wc,我尝试了'wc-l,但它崩溃了1GB文件。我试过这个C代码 它在4秒内读取一个500MB的文件 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, s

我尝试了'
wc-l
,但它崩溃了1GB文件。我试过这个C代码

它在4秒内读取一个500MB的文件

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秒


我还没试过快一点的吗?

我觉得你的答案看起来不错。我唯一要添加的是使用缓冲区大小。我觉得它可能会根据缓冲区大小改变性能


请参阅-

文件中的缓冲区大小。ReadLines
是在.NET 4.0中引入的

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

工作时间为4秒,与第一个代码片段的时间相同。您的第一种方法看起来已经是最佳解决方案了。请记住,您大多数情况下不受CPU限制,但受到HD读取速度的限制,500 MB/4秒=125MB/s的读取速度已经相当快了。唯一比这更快的方法是通过RAID或使用SSD,而不是通过更好的算法。

您是否正在寻找一种工具来高效地计算文件中的行数?如果是的话,试试MS

下面的内容将为您提供行数:

LogParser "SELECT count(*) FROM file" -i:TEXTLINE

如果你真的想要快速,考虑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);
    }
}
/*
*LineCount.c
*
*数行。。。
*
*编译时使用:
*
*c:\vc10\bin\cl.exe/O2-Ic:\vc10\Include-I\winsdk\Include
*c-link/debug/SUBSYSTEM:CONSOLE/LIBPATH:c:\vc10\Lib
*/LIBPATH:\winsdk\Lib/out:LineCount.exe
*/
#包括
#包括
#包括
无效用法(char*appname)
{
printf(“\nLineCount.exe\n”);
printf(“计算文本文件中的行数…\n\n”);
printf(“用法:\n”);
printf(“%s\n\n”,appname);
}
int linecnt(字符*文件)
{
int sz=2048;
char*buf=(char*)malloc(sz);
FILE*fp=NULL;
int n=0;
errno_t rc=fopen_s(&fp,文件“r”);
if(rc){
fprintf(stderr,“%s:fopen(%s)失败:ecode(%d)\n”,
__文件,文件,rc);
返回-1;
}
而(fgets(buf、sz、fp)){
int r=strlen(buf);
如果(buf[r-1]='\n')
n++;
//可以在这里重新分配以处理更大的线路
}
fclose(fp);
返回n;
}
int main(int argc,字符**argv)
{
如果(argc==2){
int n=linecnt(argv[1]);
printf(“行:%d\n”,n);
}
否则{
用法(argv[0]);
出口(1);
}
}
您试过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上的输入并输出行数。

@nCdy作为答案添加了您的配置文件运行时在每个配置文件中确定了哪些热点?您确定您正在测试行计数而不是文件系统吗?如果第一个测试加载文件以便缓存,那么后续测试将运行得更快。确保你真的在测试你认为正在测试的东西。吉姆·米谢尔+1。性能测试比大多数人想象的要复杂!这里有一些讨论:这是因为它基本上与您的第一个代码片段做相同的事情;)永远不要使用Count(),使用Length(File.ReadAllLines(@“yourfile”).Length;//再次检查此解决方案,但使用Length@nCdy当前位置这是一个非常糟糕的建议(在这种情况下)!请注意区别:他使用的是
File.ReadLines()
,它实际上返回一个
IEnumerable
,并且只返回一个
结果,返回的基本上是他的第一个代码片段
File.ReadAllLines()
会将所有行读取到内存中,这在性能方面会非常糟糕。当然,也就是说,如果您已经有了一个数组,那么应该使用
Length
而不是
Count()
;)@瑟维弗同意了。他不需要加载所有行,但如果他不使用它们的话。@nCdy正如SirViver所说,抛出了类型为“System.OutOfMemoryException”的异常。
我尝试了不同的值,超过256的任何值都会有相同的性能,而像4这样的较低值则较慢。我还发现我可以估计行数,获取文件大小并除以第一行的中等大小。@JaderDias:True,但是您只有一个估计值,而不是实际计数。根据文件的结构,你的估计可能会落空。您没有指定行计数的目的或文件的典型外观,因此无法提供更专业的建议。对于我的CSV文件,估计值更准确—可能更快,但我打赌差异小于10%—请稍后再试。我很想知道。10秒=(在调试时在VS2010上运行,与其他所有tests@Jader:等等,您正在调试模式下运行性能测试?永远不要这样做。您可能会得到完全误导性的结果。调试器故意对您的程序进行反优化以改善调试体验。在这种情况下,这可能不是问题,因为您是磁盘限制,而不是处理器限制,但在调试器中测量性能仍然是一种糟糕的编程实践。@Jader:就像我说的,这是因为你运气好,碰巧选择了一个性能问题,这个性能问题受磁盘硬件速度的限制。当你试图优化一些受实际代码速度限制的东西时,这就是com完全不同的故事。
flex -Cf scanner.l 
gcc -O -o lineCount.exe scanner.c