使用StreamReader.Read读取短,整数和十进制数据类型的块

时间:2010-11-08 07:49:17

标签: c# char streamreader

这些值是逗号分隔的,所以我使用stringbuilder来构建值。然后将它们写入适当的缓冲区。我注意到在builder.ToString和Parse函数中花了相当多的时间。我是否必须编写不安全的代码来克服这个问题?什么是实现我想要的最佳方式

   private static void ReadSecondBySecondFileToEndBytes(FileInfo file, SafeDictionary<short, SafeDictionary<string, SafeDictionary<int, decimal>>> dayData)
    {
        string name = file.Name.Split('.')[0];
        int result = 0;
        int index = result;
        int length = 1*1024; //1 kb
        char[] buffer = new char[length];

        StringBuilder builder = new StringBuilder();
        bool pendingTick = true;
        bool pendingSymbol = true;
        bool pendingValue = false;
        string characterString = string.Empty;
        short symbol = 0;
        int tick = 0;
        decimal value;
        using (StreamReader streamReader = (new StreamReader(file.FullName)))
        {

            while ((result = streamReader.Read(buffer, 0, length)) > 0)
            {
                int i = 0;
                while (i < result)
                {
                    if (buffer[i] == '\r' || buffer[i] == '\n')
                    {                           
                        pendingTick = true;
                        if (pendingValue)
                        {
                            value = decimal.Parse(builder.ToString());
                            pendingSymbol = true;
                            pendingValue = false;
                            dayData[symbol][name][tick] = value;
                            builder.Clear();
                        }
                    }
                    else if (buffer[i] == ',') // new value to capture
                    {                          
                        if (pendingTick)
                        {
                            tick = int.Parse(builder.ToString());
                            pendingTick = false;
                        }
                        else if (pendingSymbol)
                        {
                            symbol = short.Parse(builder.ToString());
                            pendingValue = true;
                            pendingSymbol = false;
                        }
                        else if (pendingValue)
                        {
                            value = decimal.Parse(builder.ToString());
                            pendingSymbol = true;
                            pendingValue = false;
                            dayData[symbol][name][tick] = value;
                        }
                        builder.Clear();
                    }
                    else
                        builder.Append(buffer[i]);
                    i++;
                }

            }
        }

    }

2 个答案:

答案 0 :(得分:2)

我的建议是不要像现在一样尝试解析大部分文件,但是请选择以下内容:

using (var reader = File.OpenText("<< filename >>"))
{
    string line;

    while ((line = reader.ReadLine()) != null)
    {
        string[] parts = line.Split(',');

        // Process the different parts of the line here.
    }
}

这里的主要区别是你没有解析行结尾和逗号分隔。优点是,当您使用ReadLine()等高级方法时,StreamReaderFile.OpenText()返回)可以优化逐行读取文件。 String.Split()也是如此。

使用这些高级方法几乎总是比你自己解析缓冲区更快。

使用上述方法,您不必再使用StringBuilder了,只需获取您的值:

tick = int.Parse(parts[0]);
symbol = short.Parse(parts[1]);
value = decimal.Parse(parts[2]);
dayData[symbol][name][tick] = value;

我还没有验证上面的代码段;请验证这些行是否正确,或根据您的业务逻辑更正这些行。

答案 1 :(得分:1)

你得到了错误的印象。是的,在测试程序时,您确实会在Parse()和构建器中看到大部分时间。因为这是唯一可以完成任何实际工作的代码。

但是在制作中不会这样。然后所有时间都将花在StreamReader上。因为文件不会出现在文件系统缓存中,就像在开发机器上反复运行程序时一样。在生产中,必须从磁盘驱动器读取文件。而且速度非常慢,磁盘I / O是您程序的真正瓶颈。使解析速度提高两倍只会使程序的速度提高几个百分点(如果有的话)。

不要为了这么小的收益而损害代码的可靠性或可维护性。