/// <summary> /// Пишет весь тикер в текстовый файл с учетом временных ограничений. /// Для каждого бин файла вызывается <paramref name="progress"/> /// </summary> /// <param name="tickerInfo"></param> /// <param name="range">Временной диапазон, за который конвертить данные. Если задать null то все данные брать.</param> /// <param name="progress">прогрессор. Для отчетности о выполнении работы</param> public async static Task BinToTxtTradesAsync(TradesTickerInfo tickerInfo, DateRange range, IProgress <ProgressReport> progress) { var timer = new Stopwatch(); timer.Start(); var totalProcessed = await Task.Factory.StartNew <int>(() => { #region Тело метода var trdName = "{0}.trd".Put(tickerInfo.Ticker); var trdPath = Path.Combine(tickerInfo.BinPath, trdName); var streamW = new StreamWriter(trdPath, false); streamW.WriteLine(TickTxtHeaderFull); // получим список путей до бинарников с учетом ограничений по дате var matсhingDates = range == null ? tickerInfo.Dates : tickerInfo.Dates.Where(range.Includes); var pathList = matсhingDates.Select(date => { var fileName = "{0}.{1}.bin".Put(tickerInfo.Ticker, date.ToString(TickBinFileNameDateFormat)); return(Path.Combine(tickerInfo.BinPath, fileName)); }).ToArray(); // Для каждого бинарного файла тикер, производим процедуру записи в ТХТ файл. var cache = new BinaryCache <TradeInfo>(); var filesProcessed = 0; foreach (var path in pathList) { var version = BinaryCache <TradeInfo> .ReadVersion(path); if (version == 0) { throw new Exception("Не удалось получить версию формата файла."); } // пишем в текст var trades = cache.LoadCached(path, version); trades.ForEach(t => streamW.WriteLine(t.ToFullString())); // отчитались filesProcessed++; progress.Report(new ProgressReport() { Percent = (double)filesProcessed * 100 / pathList.Length, TimeUsed = timer.Elapsed, ProcessedCount = filesProcessed }); } // Скидываем на диск и закрываем потоки. streamW.Flush(); streamW.Close(); return(pathList.Length); #endregion }); timer.Stop(); progress.Report(new ProgressReport() { Finished = true, Percent = 100, TimeUsed = timer.Elapsed, ProcessedCount = totalProcessed }); }
/// <summary> /// Перебирает все бин файлы с тиками и заменяет файлы где нашлись дубли или несортировано на новые версии. /// Старые версии сохраняет поставив перед именем префикс "__" /// </summary> /// <param name="tickerInfo"></param> /// <param name="range"></param> /// <param name="progress"></param> /// <returns></returns> public async static Task BinDeDupTradesAdync(TradesTickerInfo tickerInfo, DateRange range, IProgress <ProgressReport> progress) { var timer = new Stopwatch(); timer.Start(); var totalReplaced = await Task.Factory.StartNew <int>(() => { #region Тело метода // получим список путей до бинарников с учетом ограничений по дате var matсhingDates = range == null ? tickerInfo.Dates : tickerInfo.Dates.Where(range.Includes); var pathList = matсhingDates.Select(date => { var fileName = "{0}.{1}.bin".Put(tickerInfo.Ticker, date.ToString(TickBinFileNameDateFormat)); return(Path.Combine(tickerInfo.BinPath, fileName)); }).ToArray(); // Для каждого бинарного файла тикер, производим проверку и перезапись если нужно сортировать var cache = new BinaryCache <TradeInfo>(); var filesProcessed = 0; var filesReplaced = 0; foreach (var path in pathList) { var version = BinaryCache <TradeInfo> .ReadVersion(path); if (version == 0) { throw new Exception("Не удалось получить версию формата файла."); } // загружаем тики из бинарного кэша var trades = cache.LoadCached(path, version); // удалим дубли, и если увидим что число сделок упало, значит надо переписать исходный файл var origCount = trades.Count; var sorted = trades.Distinct(new TradeInfoComparer()).OrderBy(t => t.TradeNo).ToList(); if (sorted.Count != origCount) { var bakFileName = "__" + Path.GetFileName(path); var bakDirName = Path.GetDirectoryName(path); var bakPath = Path.Combine(bakDirName, bakFileName); File.Move(path, bakPath); cache.SaveCached(path, sorted); filesReplaced++; } // отчитались filesProcessed++; progress.Report(new ProgressReport() { Percent = (double)filesProcessed * 100 / pathList.Length, TimeUsed = timer.Elapsed, ProcessedCount = filesProcessed }); } return(filesReplaced); #endregion }); timer.Stop(); progress.Report(new ProgressReport() { Finished = true, Percent = 100, TimeUsed = timer.Elapsed, ProcessedCount = totalReplaced }); }
private async void btnDeDup_Click(object sender, RoutedEventArgs e) { // Получим выбранный тикер, если ничего не выбрали то выходим. var tickerInfo = cbxTickers.SelectedItem as TradesTickerInfo; if (tickerInfo == null) { return; } // если границы не заданы, то диапазона не будет, будем брать все. DateRange dateRange; if (dpFrom.SelectedDate == null || dpTo.SelectedDate == null) { dateRange = null; } else { var from = (DateTime)dpFrom.SelectedDate; var to = (DateTime)dpTo.SelectedDate; if (from > to) { MessageBox.Show("Дата От должна быть всегда не больше даты До.", "Ошибка!", MessageBoxButton.OK, MessageBoxImage.Error); return; } dateRange = new DateRange(from, to); } // Выключим кнопку записи в файл чтобы сто раз не жмакали // так как у нас включен биндинг, нужно его засейвить потом ресторить. var btn = ((Button)sender); BindingBase binding = null; if (BindingOperations.IsDataBound(btn, IsEnabledProperty)) { binding = BindingOperations.GetBinding(btn, IsEnabledProperty) ?? (BindingBase)BindingOperations.GetMultiBinding(btn, IsEnabledProperty); } btn.IsEnabled = false; // Инициализируем прогресс бар с учетом выбранного диапазона prgbBin2Txt.Minimum = 0; prgbBin2Txt.Maximum = 100; prgbBin2Txt.Value = 0; // прогрессор, будет апдейтить прогрессбар и строку статуса var progress = new Progress <ProgressReport>(report => { prgbBin2Txt.Value = (int)report.Percent; if (report.Finished) { lblTickProcessStatus.Content = "Заменено: {0} Затрачено: {1}".Put(report.ProcessedCount, report.TimeUsed); } else { lblTickProcessStatus.Content = "Обработано: {0} Затрачено: {1}".Put(report.ProcessedCount, report.TimeUsed); } }); // заводим асинхронно конвертацию, если будут ошибки, они хэндлятся штатным образом. try { await Common.BinDeDupTradesAdync(tickerInfo, dateRange, progress); } catch (Exception ex) { Trace.Fail(ex.ToString()); lblTickProcessStatus.Content = "Error: {0}".Put(ex.Message); this.UpdateLayout(); } // восстановим биндинг кнопки, сбросим прогрессбар btn.SetBinding(IsEnabledProperty, binding); prgbBin2Txt.Value = 0; prgbBin2Txt.UpdateLayout(); }