2012-06-24 7 views
1

У меня есть большой файл журнала, который мне нужно проанализировать с помощью F # в Windows 8. Сервер постоянно работает, который записывает в конец файла журнала, добавляя новые строки. Файлы журнала проверяются каждую минуту для внесения изменений. Вместо того, чтобы перерисовывать весь файл, я бы скорее прочитал его с конца и объединил вновь добавленные строки в результат предыдущего анализа. Еще лучше, я бы хотел просто зарегистрировать обратный вызов для всякий раз, когда файл был изменен. Это возможно?Работа с большими файлами

+0

Конечно, в идеале было бы лучше, если бы вы могли просто перенастроить сервер, который пишет до конца файла журнала, чтобы также написать некоторую услугу, которую вы раскрываете (если сервер использует log4net или даже Trace api, не должен быть слишком сложным) ... –

+0

Да, это было бы хорошо. К сожалению, сервер - это просто файл .exe, для которого у меня нет источника. –

+4

Вы можете использовать [FileSystemWatcher] (http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx) для запуска вашего обработчика. Обработчик, в свою очередь, будет помнить последнее доступное смещение (или только предыдущий размер файла), затем 'Seek()' там и читать новые строки. Обратите внимание на правильное открытие файла, чтобы не было конфликтов доступа. Это также зависит от того, как сервер открывает файл для записи. – bytebuster

ответ

1

Вы можете сделать это Seek() через фильтр. Что-то вроде этого:

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" 

Однако, по какой-то причине, на моей машине я получаю «Процесс не может получить доступ к файлу, так как он используется другим прок» ошибок, которые я не могу отследить. Операторы use должны быть утилизированы, когда они выходят за пределы области видимости, и даже явные обращения к Close не исправляют:/

+2

Если вы делаете это из разных потоков или процессов, я бы ожидал, что сообщение , Добавив еще один параметр в конце - «, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), возможно, исправит его. Но автор также должен поделиться. (Я ничего не тестировал). –

Смежные вопросы