Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Выводит путь и имя файла и программа останавливается(UPD)

#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 должен был как раз этим и заниматься: читать данные переданного в него файла (либо пути), и на основе этих данных уже проецировать объект.

Комментариев нет:

Отправить комментарий