использование StreamReader.Read для чтения блоков коротких, целых и десятичных типов данных - PullRequest
1 голос
/ 08 ноября 2010

значения разделены запятыми, поэтому я использую строитель строк для создания значений. затем запишите их в соответствующий буфер. Я заметил значительное время, проведенное в строителе. Функции 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 ]

2 голосов
/ 08 ноября 2010

Мое предложение было бы не пытаться анализировать большую часть файла, как вы делаете сейчас, а пойти на что-то вроде этого:

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(), StreamReader (который возвращает File.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 голос
/ 08 ноября 2010

У вас неправильное впечатление. Да, пока вы тестируете свою программу, вы действительно увидите, что большую часть времени проводит внутри Parse () и компоновщика. Потому что это единственный код, который выполняет какую-либо реальную работу.

Но так не будет в производстве. Тогда все время будет потрачено в StreamReader. Потому что файл не будет присутствовать в кеше файловой системы, как при повторном запуске программы на компьютере разработчика. В производстве файл должен быть прочитан с диска. И это невероятно медленно, дисковый ввод-вывод является истинным узким местом вашей программы. Ускорение синтаксического анализа в два раза сделает вашу программу на несколько процентов быстрее, если вообще.

Не ставьте под угрозу надежность или удобство сопровождения вашего кода при таком небольшом выигрыше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...