C#提高计划的效率?

buz*_*jay 3 c# file-io visual-studio-2010 streamreader c#-4.0

我正在开发一个C#程序,它读取非常大的文件并检查它们是否有不同的属性和字段.我一直在测试不到100万行的文件,并按预期进行预编译.我最近在一个包含250万行的文件上进行了测试,花了4个小时才完成.

我正在使用自定义阅读功能读取每个字符,以便我可以找到所有CR和LF,因为每行包含它们非常重要.我已经单独测试了阅读功能,它看起来大约需要14分钟来读取文件,我觉得这个文件足够合理,可以读取250个行中1500个字符的每个字符.我将包括我阅读功能,但这似乎并没有导致问题.

我的阅读功能将每个字符添加到一个字符串,然后我检查字符串中的不同值.例如,行长度是否正确,文件是否包含标题,标题是否包含正确的值.以及特定值如char位置403-404一个数字,是字段1250-1300不为空等.

我的问题是我能做些什么来弄清楚导致速度减慢的原因并提高我的程序效率?我已经尝试检查每个循环开始和结束时的时间,但似乎没有改变.但是,每100,000人需要的时间比以前长得多.例如,处理线10,000到20,000花费不到3秒,830,000到840,000花费约35秒.我曾考虑尝试多个线程,但不认为在我从文件中读取行的情况下它会有所帮助.思考?谢谢您的帮助!

    static void ReadMyLine(ref string currentLine, string filePath, ref int asciiValue, ref Boolean isMissingCR, ref Boolean isMissingLF, ref Boolean isReversed, ref StreamReader file)
    {
        Boolean endOfRow = false;
        isMissingCR = false;
        isMissingLF = false;
        isReversed = false;

        currentLine = "";

        while (endOfRow == false)
        {
            asciiValue = file.Read();

            if (asciiValue == 10 || asciiValue == 13)
            {
                int asciiValueTemp = file.Peek();

                if (asciiValue == 13 && asciiValueTemp == 10)
                {
                    endOfRow = true;
                    asciiValue = file.Read();
                }
                else if (asciiValue == 10 && asciiValueTemp == 13)   // CRLF Reversed
                {
                    asciiValue = file.Read();
                    endOfRow = true;
                    isReversed = true;
                }
                else if (asciiValue == 10)                           // Missing CR
                {
                    isMissingCR = true;
                    endOfRow = true;
                }
                else if (asciiValue == 13)                           // Missing LF
                {
                    isMissingLF = true;
                    endOfRow = true;
                }
                else
                    endOfRow = true;
            }
            else if (asciiValue != -1)
                currentLine += char.ConvertFromUtf32(asciiValue);
            else
                endOfRow = true;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 11

这是我要找的第一件事,也是我要改变的第一件事:

currentLine += char.ConvertFromUtf32(asciiValue);
Run Code Online (Sandbox Code Playgroud)

不要那样做.在循环中使用字符串连接可以杀死性能-你得到O(N 2)的复杂性.请StringBuilder改用.请参阅我的文章,了解何时使用StringBuilder更多解释.

你可能会做更多的事情,但只是改用StringBuilder它将是一个巨大的进步:

StringBuilder builder = new StringBuilder();
while (...)
{
    ...
    builder.Append(char.ConvertFromUtf32(asciiValue));
}
currentLine = builder.ToString();
Run Code Online (Sandbox Code Playgroud)

不清楚为什么你有这么多ref参数.你为什么要传球asciiValue?你为什么要StreamReader通过参考?使用这么多ref参数的任何东西都让我非常紧张 - 你为什么不拥有一个封装你真正希望从方法返回的所有东西的类型?

您可能希望阅读有关参数传递的文章,以便更好地理解ref.

  • @buzzzzjay:你永远不会改变`file`的值,为什么``ref`?如果你只想要'asciiValue`*out*的值,你应该使用`out`参数 - 或者返回值!使用ref参数的void方法真的很难看.但看起来该方法确实想要返回几条信息:因此声明一个类型来封装该信息,并使其成为该方法的返回类型. (2认同)