Voilà mon petit exemple, vite fait, donc largement perfectible.
Le résultat visuel d'abord
Sur form1 du projet (et namespace) TestWinform, il y a 2 DateTimePicker au Format Time, une ListBox et un DataGridView.
Dans la listBox n'apparaissent que les erreurs présentent dans l'intervalle de temps.
Quand on sélectionne une erreur, toutes les occurrences dans l'intervalle de temps apparaissent dans le DataGridView.
Pour en arriver là, j'ai écrit une classe Log, avec 3 propriétés Datation, Erreur et Details (bien sûr si le découpage que j'ai fait doit être plus fin c'est largement gérable) et une méthode permettant de Parser les lignes de ton fichier.
Si le format n'est pas reconnu, j'ai généré une erreur, ça te permettra en mode debug de copier coller ici la ligne qui ne fonctionne pas pour améliorer le découpage.
Voici cette classe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Test_Winform
{
class Log
{
public DateTime Datation { get; set; }
public string Erreur { get; set; }
public string Details { get; set; }
public static Log Parse(string Ligne)
{
//utilisation d'un regex pour tester le format et faire un premier découpage de la ligne
Match m = Regex.Match(Ligne, @"^(?<moi>\d\d?)/(?<jour>\d\d?)/(?<annee>\d{4})\s+(?<heure>\d\d?):(?<minute>\d\d?):(?<seconde>\d\d?)\s+(?<ampm>[AP]M):(?<ms>\d{1,3})\s+(?<erreur>.+?)::(?<details>.+)$");
if (m.Success)
{
//il faut découper les valeurs de datation, car DateTime.Parse n'aime le jours, mois, heures, minutes, secondes sur 1 chiffre
int jour = int.Parse(m.Groups["jour"].Value);
int moi = int.Parse(m.Groups["moi"].Value);
int annee = int.Parse(m.Groups["annee"].Value);
int heure = int.Parse(m.Groups["heure"].Value);
int minute = int.Parse(m.Groups["minute"].Value);
int secondes = int.Parse(m.Groups["seconde"].Value);
//si ce nombre est bien des ms, alors 47 venant après 466 dans l'exemple 47 vaut 470, par extension 5 vaudrait 500
string MS = m.Groups["ms"].Value;
int ms = int.Parse(MS);
if (MS.Length == 1)
ms *= 100;
else if (MS.Length == 2)
ms *= 10;
DateTime date = new DateTime(annee, moi, jour, heure, minute, secondes, ms);
//Ajustement AP PM
if (m.Groups["ampm"].Value == "PM")
date = date.AddHours(12);
return new Log
{
Datation = date,
Erreur = m.Groups["erreur"].Value,
Details = m.Groups["details"].Value
};
}
throw new Exception("Format de ligne non reconnu");
}
}
}
et le code behind de form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Test_Winform
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ChargerFichier();
//dtpDebut et dtpFin sont des DateTimePicker dont le format d'affichage est "Time"
dtpDebut.Value = lesLogs.First().Datation;
dtpFin.Value = lesLogs.Last().Datation;
}
List<Log> lesLogs = new List<Log>();//liste de tous les logs
private void ChargerFichier()
{
string[] lignes = File.ReadAllLines("test.txt");//chaque ligne est chargée dans un emplacement de tableau
foreach(string l in lignes)//on itère le tableau pour créer la liste de logs
{
lesLogs.Add(Log.Parse(l));
}
}
private void DateTimePicher_ValueChanged(object sender, EventArgs e)
{
//les événements ValueChanged de dtpDebut et dtpFin sont tous deux abonnées à cette méthode
IEnumerable<Log> logsFiltres = lesLogs.Where(l => l.Datation >= dtpDebut.Value && l.Datation <= dtpFin.Value);//requête qui filtre les logs par date
List<IGrouping<string, Log>> logsGroupes = logsFiltres.GroupBy(l => l.Erreur).ToList();//regroupement des logs filtrés par erreur
lbxErreurs.DataSource = null;
lbxErreurs.DataSource = logsGroupes;
lbxErreurs.DisplayMember = "Key";//les logs groupés sont affichés dans la listBox
}
private void lbxErreurs_SelectedIndexChanged(object sender, EventArgs e)
{
//L'évènement SelectIndexChanged de la listBox est abonné à cette méthode.
if (lbxErreurs.SelectedIndex == -1)
return;// rien n'est sélectionné => on sort
ListBox lbx = sender as ListBox;
IGrouping<string, Log> logGroupe = lbx?.SelectedItem as IGrouping<string, Log>;
if (logGroupe == null)
return; //Y'a un problème => on sort
dgwLog.DataSource = null;
dgwLog.DataSource = logGroupe.ToList();//on affiche les log dans le créneau horaire, avec l'erreur sélectionnée
}
}
}