Filewatcher - afficher les modifications d'un fichier en temps réel

Soyez le premier à donner votre avis sur cette source.

Vue 15 645 fois - Téléchargée 840 fois

Description

Ce petit programme permet d'afficher le contenu d'un fichier et recharger automatiquement celui-ci s'il est modifié.

Plusieurs aspects peuvent être intéressant dans ce programme
  • Utilisation du FileSystemWathcher (voir nombreux articles sur le sujet)
  • Utilisation du BackgroundWorker pour le chargement de fichier en tâche de fonds
  • Utilisation de l'éditeur de texte de CSharpDevelop

Source / Exemple :


using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace Editor
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// Nom du fichier chargé
        /// </summary>
        private string filename;

        /// <summary>
        /// Taille actuellement chargée du fichier
        /// </summary>
        private int filesize = 0;

        /// <summary>
        /// Constructeur
        /// </summary>
        public Form1()
        {
            InitializeComponent();            
        }

        #region Events
        /// <summary>
        /// Evénements déclenché lorsque le fichier surveillé est modifié
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
        {
            try
            {
                // Chargement du fichier surveillé
                LoadFile(filename);               
            }
            catch (Exception ex)
            {
                string errorMessage = ex.Message;
                while (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                    errorMessage += "\n" + ex.Message;
                }
                MessageBox.Show(errorMessage, "Unexpected error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        /// <summary>
        /// Sélection d'un fichier à surveiller et chargement de celui-ci
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonLoad_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    // Initialisation à zéro de la taille du fichier déjà chargé
                    filesize = 0;
                    // Sauvgarde du nom du fichier à charger
                    filename = openFileDialog1.FileName;
                    // Affichage du nom du fichier dans la barre de titre de la fenetre
                    this.Text = "FileWatcher - " + filename;
                    // Chargement du fichier sélectionné
                    LoadFile(filename);
                }
                catch (Exception ex)
                {
                    string errorMessage = ex.Message;
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                        errorMessage += "\n" + ex.Message;
                    }
                    MessageBox.Show(errorMessage, "Unexpected error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        /// <summary>
        /// Permet d'arrêter ou reprendre le suivi du fichier chargé
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStop_Click(object sender, EventArgs e)
        {
            if (buttonStop.Text == "Stop")
            {
                fileSystemWatcher1.EnableRaisingEvents = false;
                buttonStop.Text = "Start";
            }
            else
            {
                fileSystemWatcher1.EnableRaisingEvents = true;
                buttonStop.Text = "Stop";
            }
        }
        #endregion

        private void LoadFile(string filename)
        {
            // Si il y a déjà une tâche de fonds l'arrêter
            if (backgroundWorker.IsBusy)
                backgroundWorker.CancelAsync();
            // Attendre pour etre certain qu'il n'y  plus de tâche de fonds en cours
            while (backgroundWorker.IsBusy) ;
            // Activer la barre de chargement
            toolStripProgressBar.Visible = true;
            // Lancer le chargement en arrière plan
            backgroundWorker.RunWorkerAsync(filename);
        }

        #region delegate
        private delegate void setProgressBarPecentage(int percentage);
        /// <summary>
        /// Procédure pour afficher l'état d'avancement du chargement du fichier
        /// </summary>
        /// <param name="percentage"></param>
        private void SetProgressBarPecentage(int percentage)
        {
            toolStripProgressBar.Value = percentage;
        }

        #endregion

        #region worker
        /// <summary>
        /// Routine qui est exécutée en tâche de fonds
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {                      
            try
            {
                // Récupération du handle sur le process en cours
                BackgroundWorker worker = sender as BackgroundWorker;
                // ouverture du fichier en mode partagé
                FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                // Positionnement à l'endroit jusqu'où on avait déjà lu le fichier
                fs.Seek(filesize, SeekOrigin.Begin);
                // Total de byte déjà lu dans le fichier
                int totalRead = filesize;
                // Nouvelle taille du fichier
                filesize = (int)fs.Length;
                
                // Initialisation du buffer de lecture
                byte[] buffer = new byte[1024];
                // Nbre de caractère lu à chaque incrément
                int count = 0;
                // Chaîne de réception pour la lecture du fichier
                string texte = "";
                while ((count = fs.Read(buffer, 0, 1024)) != 0 && !worker.CancellationPending)
                {                    
                    totalRead += count;
                    // Transformation du tableau byte[] en string
                    texte += Encoding.ASCII.GetString(buffer, 0, count);
                    // Modification de l'état d'avancement
                    worker.ReportProgress((totalRead * 100) / filesize);
                }
                // Initialisation de la chaîne de retour avec le contenu du fichier
                e.Result = texte;
                // Fermeture du Flux
                fs.Close();

                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                }
            }
            catch (Exception ex)
            {
                string errorMessage = ex.Message;
                while (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                    errorMessage += "\n" + ex.Message;
                }
                MessageBox.Show(errorMessage, "Unexpected error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            
        }
                
        /// <summary>
        /// Mise à jour de la barre de progression
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // Vérification si on est dans un thread et éventuellement appel du délégate pour pouvoir faire mise à jour
            if (this.InvokeRequired)
                this.Invoke(new setProgressBarPecentage(SetProgressBarPecentage), new object[] { e.ProgressPercentage });
            else
                SetProgressBarPecentage(e.ProgressPercentage);            
        }
        /// <summary>
        /// Méthode appelée lorsque le fichier a été chargé
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Vérification si tout s'est bien déroulé
            if (e.Cancelled)
            {
                // L'utilisateur à annulé l'opération
                toolStripStatusLabel1.Text = string.Format("Aborted by user.");
            }
            else if (e.Error != null)
            {
                // Il y a eu une erreur pendant le traitement.
                string msg = String.Format("An error occurred: {0}", e.Error.Message);
                MessageBox.Show(msg);
            }
            else
            {
                // Tout s'est bien déroulé
                // Affichage du fichier dans le contrôle ICsharpCode.TextEditor
                textEditorControl1.Text += e.Result.ToString();
                // Calcul du nombre de ligne dans le contrôle ICsharpCode.TextEditor
                int totalLine = textEditorControl1.Document.GetLineNumberForOffset(textEditorControl1.Text.Length);
                // Déplacement jusqu'à la dernière ligne
                textEditorControl1.ActiveTextAreaControl.ScrollTo(totalLine, 1);
                // Affichage d'inforamtions dans la barre du d'info du bas de l'écran
                toolStripStatusLabel1.Text =
                    string.Format("{0} lines - last accesss : {1} - {2} ", totalLine,
                                  File.GetLastWriteTime(filename).ToShortDateString(),
                                  File.GetLastWriteTime(filename).ToLongTimeString());
                // Initialisation de la surveillance du fichier chargé
                fileSystemWatcher1.Filter = Path.GetFileName(filename);
                fileSystemWatcher1.Path = Path.GetDirectoryName(filename);
                fileSystemWatcher1.EnableRaisingEvents = true;
                // Activation du boutton d'arrêt de surveillance
                buttonStop.Enabled = true;
            }
            // Cacher la barre de progression du chargement de fichier
            toolStripProgressBar.Visible = false;
        }
        #endregion
    }
}

Conclusion :


Ce programme, comme pratiquement tous, peut être amélioré, mais il remplit mais besoin actuel...

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_Warny
Messages postés
478
Date d'inscription
mercredi 7 août 2002
Statut
Membre
Dernière intervention
10 juin 2015
-
Salut,
Dans ton exemple tu montres un fichier de trace www. Je te conseille de prévoir le cas (à la discrétion de l'utilisateur) d'une modification par ajout en ne rechargeant que la fin du fichier à chaque modif. Tu gagnerait ainsi un temps précieux.
Sinon, pour lire une fichier texte, tu peux utiliser un textStream et la fonction ReadToEnd pour le lire en une fois.
cs_pdl
Messages postés
134
Date d'inscription
mardi 20 novembre 2001
Statut
Membre
Dernière intervention
16 juin 2008
-
Bonjour,

Si tu regardes bien la source, tu verras que je ne recharge que la fin du fichier s'il y a une modification de celui-ci. C'est la raison pour laquelle j'utilise la variable filesize qui me permet de sauver le nombre d'octets que j'ai déjà lu et de faire ensuite un seek.
Pour le textStream, cela pose un problème si le fichier est déjà ouvert par un processus quelconque. J'étais parti sur ce principe, mais si tu veux monitorer un fichier log d'apache, par exemple, et bien tu ne sais tout simplement pas ouvrir le fichier et c# te prévient gentiment que le fichier est déjà ouvert par quelqu'un d'autre.
cs_Warny
Messages postés
478
Date d'inscription
mercredi 7 août 2002
Statut
Membre
Dernière intervention
10 juin 2015
-
Autant pour moi, je n'avais pas repéré la variable.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.