#c_sharp
Задание и код исправленный взяты отсюда: Парсинг и статистика,недопонимание ситуации с преобразованием,аргументами На это фрагменте кода программа останавливается она выдаёт путь и название 2 текстовых файлов которые у меня в папке и всё, программа перестает дальше выполняться. Отладка делалась пошагово. string logDir = @"D:\logfiles\"; ; var userstat = new Stat(); var cq = new ConcurrentQueue(); // параллельно ... Directory.EnumerateFiles(logDir, "log*.txt").AsParallel().ForAll(file => { Console.WriteLine("@" + Environment.CurrentManagedThreadId + "\t" + file); // собрать статистику из файла foreach (var line in Line.ParseFiles(logDir,file, 1)) userstat.Add(line.User, line); // сохранить статистику для дальнейшего агрегирования cq.Enqueue(userstat); }); Весь код программы: using System; using System.Collections.Generic; using System.Linq; using System.IO; using System.Data; using System.Collections.Concurrent; using System.Text.RegularExpressions; using System.Threading; using System.Text; using System.Threading.Tasks; namespace LabWork2 { public class Line { public string User; public string Address; public int Traffic; public DateTime Date; public string ToCsv(bool header = false) { var s = ", "; return header ? String.Concat("User", s, "Address", s, "Traffic", s, "Date") : String.Concat( this.User, s, this.Address, s, this.Traffic, s, this.Date.ToString("d.MM")); } public static IEnumerable ParseFiles(string logDir, string pattern = "log?.txt", int skip = 0) { string result = Path.GetFileName(pattern); foreach (var file in Directory.EnumerateFiles(logDir, result)) while (File.Exists(pattern)) { foreach (var line in ParseFile(logDir, result, 1)) yield return line; } } public static IEnumerable ParseFile(string logDir,string pattern, int skip = 0) { return ParseFiles(logDir,pattern,skip); } } class Stat { public class Item { public string Key; public int Traffic; public DateTime From; public DateTime To; public string ToCsv(bool header=false) { var s = ", "; return header ? String.Concat("Key", s, "Traffic", s, "From", s, "To") : String.Concat( this.Key, s, this.Traffic, s, this.From.ToString("d.MM"), s, this.To.ToString("d.MM")); } } Dictionary tbl = new Dictionary (); public void Add(string key, Line line) { Item itm; if (tbl.TryGetValue(key, out itm) == false) { itm = new Item { Key = key, From = line.Date, To = line.Date }; tbl.Add(key, itm); } itm.From = new DateTime(Math.Min(itm.From.Ticks, line.Date.Ticks)); itm.To = new DateTime(Math.Max(itm.To.Ticks, line.Date.Ticks)); itm.Traffic += line.Traffic; } public IEnumerable - Items { get { return tbl.Values; } } } class Program { static void Main(string[] args) { string logDir = @"D:\logfiles\"; ; var userstat = new Stat(); var cq = new ConcurrentQueue
(); // параллельно ... Directory.EnumerateFiles(logDir, "log*.txt").AsParallel().ForAll(file => { Console.WriteLine("@" + Environment.CurrentManagedThreadId + "\t" + file); // собрать статистику из файла foreach (var line in Line.ParseFiles(logDir,file, 1)) userstat.Add(line.User, line); // сохранить статистику для дальнейшего агрегирования cq.Enqueue(userstat); }); Console.WriteLine(cq.Count); File.WriteAllLines(logDir + "userstat.txt",userstat.Items.Select(si => si.ToCsv())); File.WriteAllLines(logDir + "adrestat.txt",userstat.Items.Select(si => si.ToCsv())); File.WriteAllLines(logDir + "datastat.txt", userstat.Items.Select(si => si.ToCsv())); Console.ReadKey(); } } } UPD UPD UPD Исключение исчезло! Спасибо за помощь! Учёл предыдущие советы присвоил отдельную переменную и даже извлекаю имя c Path.GetFileName(pattern) и уже работаю с ней. В итоге он уже пишет переполнение стэка и на этой же строке. Циклом while пройтись по папке с файлами? По шагово отладчиком я ходил и у меня выдало logDir = "D:\\logfiles\\" string pattern "D:\\logfiles\\log1.txt" string result = "log1.txt" string Убрал лишнее и теперь переменная result мне выдаёт имя файла. Но исключение Стэк переполнен... static IEnumerable Parse(IEnumerable lines) { foreach (var line in lines) { var arr = Regex.Split(line.Trim(), @"\s+"); yield return new Line { User = arr[0], Address = arr[1], Traffic = int.Parse(arr[2]), Date = DateTime.ParseExact(arr[3], "d.MM", null) }; } } public static IEnumerable Parse(string logDir, string pattern = "log?.txt", int skip = 0) { string result = Path.GetFileName(pattern); foreach (var file in Directory.GetFiles(logDir,result))----Переполнение стэка Исключение. { foreach (var line in ParseFile(logDir, file, 1)) yield return line; } } public static IEnumerable ParseFile(string logDir,string file, int skip = 0) { return Parse(logDir,file, skip); }
Ответы
Ответ 1
У вас неправильный паттерн. Паттерн должен указываться для имени файла. А у вас он указан для всего пути. Можете указать такой паттерн: pattern = "log*.txt" ? - вместо него может быть ноль или один символ. * - а вместо него уже ноль или несколько символов. UPD: Автор вопроса меняет/дополняет вопрос. Дополню свой ответ, почему же у него не выходит. Программа работает, просто она бесконечно выполняет одни и те же действия, из-за странного алгоритма. Опишу в порядке вызовов, что происходит (прим. вместо аргументов и параметров я укажу их значения): Вызов метода ParseFiles("D:\logfiles\", "D:\logfiles\log1.txt", 1). В его теле метод File.Exist("D:\logfiles\log1.txt") вернет true, поэтому будет заход в тело цикла (зачем он вообще?), произойдет вызов метода ParseFile("D:\logfiles\", "log1.txt", 1) [следующий пункт]. Вызов метода ParseFile("D:\logfiles\", "log1.txt", 1). Сам он вызывает метод ParseFiles("D:\logfiles\", "log1.txt", 1) [следующий пункт]. Зачем? Что это за логика? Вызов метода ParseFiles("D:\logfiles\", "log1.txt", 1). В его теле метод File.Exist("log1.txt") вернет false (что логично), произойдет выход из метода ParseFiles. Идет возврат к 1 пункту. И т.д. Очень корявый алгоритм, который еще и не работает. Зачем-то параметр skip, который нигде не используется. И это можно было бы отследить через отладку очень легко. Не знаю, почему вы ничего не заметили. Вы хотите распарсить лог, но этой логики я не увидел в Вашем коде, только чтение списка файлов в папке. Метод ParseFile должен был как раз этим и заниматься: читать данные переданного в него файла (либо пути), и на основе этих данных уже проецировать объект.
Комментариев нет:
Отправить комментарий