En utilisant MemoryMappedFile et FileSystemWatcher pour détecter de nouvelles entrées à logFile

StackOverflow https://stackoverflow.com/questions/4198692

  •  11-10-2019
  •  | 
  •  

Question

J'ai un fichier journal qui est écrit par une application 3ème partie et je voudrais ma demande à « lire » ce fichier journal en temps réel / temps quasi, parse les nouvelles entrées du journal et agir sur certains événements.

Ma pensée était que je pouvais y parvenir avec une combinaison de FileSystemWatcher (aux changements de fichiers de signaux) et MemoryMappedFile (pour poursuivre la lecture à partir d'un certain décalage).

Cependant, comme cela est la première fois que je utilise MemoryMappedFiles je INTRODUISE des problèmes qui se posent sans doute de ne pas comprendre le concept correctement (par exemple, je suis incapable d'ouvrir le fichier existant car il est utilisé par l'autre processus ).

Je me demandais si quelqu'un a un exemple de la façon d'utiliser MemoryMappedFiles pour lire un fichier qui est verrouillé par un autre processus?

Merci,

Tom

EDIT:

D'après les commentaires, il semble que la mémoire mappée fichiers ne me aider à accéder à des fichiers qui ont un verrou exclusif. Cependant, les outils « queue » comme, par exemple BareTail (http://www.baremetalsoft.com/baretail/index.php) sont en mesure de le faire. Il n'a aucun problème à lire le fichier qui a un verrou exclusif d'une autre application à des intervalles de 1 s). Donc, il doit y avoir une façon de le faire?

editEdit :

Pour répondre à ma propre question, l'affaire dans l'ouverture d'un fichier verrouillé est, en créant le FileStream avec les drapeaux d'accès suivants:

fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);
Était-ce utile?

La solution

Pour répondre à ma propre question, l'astuce dans la lecture d'un fichier verrouillé crée le FileStream avec les drapeaux d'accès suivants:

FileStream fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);

Maintenant, il est juste une question de l'un intervalle faisant fonction sondages ou à la recherche d'événements de changement FileSystemWatcher pour détecter les changements de fichiers

Autres conseils

Je ne sais pas si MemoryMappedFiles allez vous aider. Jetez un oeil à FileStream:

var stream = new FileStream(path, FileMode.Open, FileShare.Read);
stream.Seek(offset, SeekOrigin.Begin);

Bien que si l'application 3ème partie a le fichier verrouillé exclusivement, il n'y a pas grand-chose que vous pouvez faire à ce sujet ...

[Début 2 EDIT]

Une autre idée ...

Si l'application tiers arrive à utiliser un cadre de l'exploitation forestière comme NLog, log4net ou System.Diagnostics, vous pouvez toujours écrire votre propre cible / Appender / TraceListener et acheminer les messages quelque part que vous pouvez les regarder (comme un fichier non ouvert exclusivement, à un autre processus, etc.).

Si votre application tierce utilise un cadre de l'exploitation forestière, nous aurait probablement entendu parler maintenant; -)

[Fin 2e EDIT]

[Début EDIT]

Je crois que je mal lu la question. Il semblait tout d'abord comme vous utilisiez une bibliothèque tierce partie qui avait mis en œuvre la journalisation et que vous vouliez faire l'analyse syntaxique à partir du programme qui générait l'exploitation forestière. Ayant Relisez votre question, il semble que vous voulez « écouter » le fichier journal de l'extérieur de l'application. Si tel est le cas, ma réponse ne sera probablement pas vous aider. Désolé.

[Fin EDIT]

Je n'ai rien à offrir au sujet MemoryMappedFiles, mais je me demande si vous pouvez réaliser ce que vous êtes après en écrivant un écouteur personnalisé / target / appender pour le système d'enregistrement 3ème partie?

Par exemple, si vous utilisez NLog, vous pouvez écrire une coutume cible et diriger tous vos messages de journalisation là-bas (tout en les orientant vers les « vrais » cible (s)). De cette façon, vous obtenez le crack à chaque message du journal tel qu'il est connecté (il est en fait en temps réel, pas en temps quasi réel). Vous pouvez faire la même chose avec log4net et System.Diagnostics.

Notez que NLog a même une cible "MethodCall". Pour utiliser ce que vous suffit d'écrire une méthode statique avec la signature correcte. Je ne sais pas si log4net a un concept similaire à ce sujet.

Cela semble qu'il serait plus facile de faire fonctionner de manière fiable que d'essayer de lire et d'analyser le fichier journal comme il est écrit par le logiciel tiers.

Si le fichier est « utilisé », il n'y a rien qui peut être fait à ce sujet. Il est vraiment « utilisé ». MemoryMappedFiles sont soit pour lire de grandes quantités de données hors du lecteur ou le partage des données avec d'autres programmes. Il ne sera pas d'aide pour contourner la limitation « en utilisation ».

Les fichiers Memorymapped sont sous les mêmes restrictions que FileStream vous initialisez avec, assurez-vous que vous initialisez votre fichier-mémoire-mappée comme ceci

var readerStream = new FileStream (chemin, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

mmf var = MemoryMappedFile.CreateFromFile (readerStream, null, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.None, false);

Si un autre processus ont complètement fermée à clef même d'écrire que vous êtes dans la malchance, ne sais pas s'il y a un moyen de contourner cela. Peut-être utiliser une minuterie détectez lorsque le processus a cessé d'écrire à lui.

Je l'ai fait quelque chose de similaire juste pour la surveillance des fichiers journaux sur une console (par opposition au traitement), mais les principes sont les mêmes. Comme vous, j'utiliser un FileSystemWatcher, et la logique est importante dans mon gestionnaire d'événements OnChanged:

case WatcherChangeTypes.Changed:
{
    System.IO.FileInfo fi = new FileInfo(e.FullPath);

    long prevLength;

    if (lastPositions.TryGetValue(e.FullPath, out prevLength))
    {
        using (System.IO.FileStream fs = new FileStream(
           e.FullPath, FileMode.Open, FileAccess.Read))
        {
            fs.Seek(prevLength, SeekOrigin.Begin);
            DumpNewData(fs, (int)(fi.Length - prevLength));
            lastPositions[e.FullPath] = fs.Position;
        }
    }
    else
      lastPositions.Add(e.FullPath, fi.Length);

    break;
}

où lastPositions est

Dictionary<string, Int64> lastPositions = new Dictionary<string, long>();

et DumpNewData est simplement

private static void DumpNewData(FileStream fs, int bytesToRead)
{
    byte[] bytesRead = new byte[bytesToRead];
    fs.Read(bytesRead, 0, bytesToRead);
    string s = System.Text.ASCIIEncoding.ASCII.GetString(bytesRead);
    Console.Write(s);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top