2012-06-24 5 views
1

J'ai un fichier journal volumineux dont j'ai besoin pour analyser avec F # sur Windows 8. Un serveur est constamment en cours d'exécution qui écrit à la fin du fichier journal en ajoutant de nouvelles lignes. Les fichiers journaux sont vérifiés chaque minute pour les modifications. Au lieu de réécrire le fichier entier, je préférerais juste lire à la fin et combiner les lignes nouvellement ajoutées au résultat de l'analyse précédente. Mieux encore, j'aimerais simplement pouvoir enregistrer un rappel à chaque fois que le fichier est modifié. Est-ce possible?Traitement de fichiers volumineux

+0

Bien sûr, idéalement, ce serait mieux si vous pouvez simplement reconfigurer le serveur qui écrit à la fin du fichier journal à écrire également à un service que vous exposer (si le serveur utilise log4net ou même l'API de trace, ne devrait pas être trop dur) ... –

+0

Ouais, ce serait bien. Malheureusement, le serveur est juste un .exe dont je n'ai pas la source. –

+4

Vous pouvez utiliser [FileSystemWatcher] (http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx) pour déclencher votre gestionnaire. Le gestionnaire, à son tour, se souviendrait du dernier décalage consulté (ou juste la taille du fichier précédent), puis 'Seek()' là et lirait les nouvelles lignes. Portez votre attention à l'ouverture du fichier correctement afin qu'il n'y ait pas de conflits d'accès. Cela dépend aussi de la façon dont le serveur ouvre le fichier pour l'écriture. – bytebuster

Répondre

1

Vous pouvez le faire soit Seek() via le flux de fichiers. Quelque chose comme ceci:

open System.IO 

let WatchLog directory file = 
    // Keep track of last read position 
    let lastRead = ref 0L 

    // Function that's called whenever the file changes 
    let processLog (e : FileSystemEventArgs) = 
     // Open file, and seek to the last read location 
     use fs = new FileStream(Path.Combine(directory, file), FileMode.Open, FileAccess.Read) 
     fs.Seek(!lastRead, SeekOrigin.Begin) |> ignore 

     // Read the rest of the file 
     use sr = new StreamReader(fs) 
     printfn "Reading log: %A" (sr.ReadToEnd()) 

     // Store the length so that we know how much to seek over next time 
     lastRead := fs.Length 
     () 

    // Create a FS watched to be notified when a file changes 
    let fs = new FileSystemWatcher(directory, file) 
    fs.Changed.Add(processLog) 
    fs.EnableRaisingEvents <- true 

WatchLog "M:\Coding\" "TestLog.txt" 

Cependant, pour une raison quelconque, sur ma machine je reçois « Le processus ne peut pas accéder au fichier car il est utilisé par un autre proc » erreurs, que je ne peux pas retrouver. Les déclarations doivent être use débarrassent quand ils sont hors de portée, et même des appels explicites à Close ne résout pas:/

+2

Si vous faites cela à partir de différents threads ou processus, alors je m'attendrais à ce message . Ajouter un paramètre supplémentaire à la fin - ", FileMode.Open, FileAccess.Read, FileShare.ReadWrite) - le corrigera peut-être, mais l'auteur doit également partager (je n'ai rien testé). –

Questions connexes