Мониторинг текстового файла
Модератор: Модераторы
Мониторинг текстового файла
Здравствуйте всем,
какими средствами, методами, способами можно в реальном времени отслеживать изменения в текстовом файле?
Есть программа, которая пишет логи в текстовый файл. Мне из моей софтины. надо отслеживать записи в этот файл..
какими средствами, методами, способами можно в реальном времени отслеживать изменения в текстовом файле?
Есть программа, которая пишет логи в текстовый файл. Мне из моей софтины. надо отслеживать записи в этот файл..
У каждого файла есть Дата/Время создания и изменения. Проверяешь дату изменения и запоминаешь ее. Потом сравниваешь читал ты этот файл или нет.
Sharfik писал(а):У каждого файла есть Дата/Время создания и изменения. Проверяешь дату изменения и запоминаешь ее. Потом сравниваешь читал ты этот файл или нет.
Это понятно, но меня это не устраивает - надо в реальном времени отслеживать появление записи в файле, она может появится через 10 секунд, а может и через 5 минут...
Вобщем нужен типа аналога юниксовой команды tail -f
arriah писал(а):надо в реальном времени отслеживать появление записи в файле, она может появится через 10 секунд, а может и через 5 минут...
Ну дак и настройте диапазон проверки даты-времени изменения файла на то время, которое считаете необходимым. Если файл не слишком большой, то его можно грузить в TStringList, запоминая кол-во строк. При следующей загрузке те строки, что окажутся больше прошлого запоминаяния и будут новыми.
Vadim писал(а):Ну дак и настройте диапазон проверки даты-времени изменения файла на то время, которое считаете необходимым. Если файл не слишком большой, то его можно грузить в TStringList, запоминая кол-во строк. При следующей загрузке те строки, что окажутся больше прошлого запоминаяния и будут новыми.
А если измениться алгоритм записи логов, то его программа "екнится"
arriah писал(а):Это понятно, но меня это не устраивает - надо в реальном времени отслеживать появление записи в файле, она может появится через 10 секунд, а может и через 5 минут...
Вобщем нужен типа аналога юниксовой команды tail -f
В реальном времени, это в реальном времени - проверять по времени каждую секунду/минуту
А выводить конец файла, это выводить конец файла - за уши притянутая правда.
Sharfik писал(а):В реальном времени, это в реальном времени - проверять по времени каждую секунду/минуту
А выводить конец файла, это выводить конец файла - за уши притянутая правда.
Суть вот в чем. Стороння программа считывает файл конфигурации и согласно ему выполняет свои действия и пишет в лог.
Если бы просто выводить лог в моей программе - это полбеду, достточно по таймеру LoadFromFile в Memo выводит. Но сложность в том, что в лог попадает не вся информация из конфигурационного файла, а мне именно ее надо выводить. То есть алгоритм такой:
Получить последню запись из лога, сравнить эту запись из файла конфигурации сторонней программы и вывести результат. Осложнение в том, что сторонний софт читает файл конфигурации в рандомном порядке.
Есть такой файловый менеджер фар. я проводил такой эксперимент:
Запустил программу, в FAR открыл на просмотр лог этой программы. Так вот когда когда программа писла в лог, в FAR это было видно... вот надо что-то подобное.
В каждой OS есть свои методы для отслеживания.
Вот обзорная статья.
Если знатоки знают платформонезависимое решение на fpc...
Вот обзорная статья.
Если знатоки знают платформонезависимое решение на fpc...
Чего-то у меня не получается.. скорее всего чего-то недопонимаю, прощу помочь.
Решил читать файл в отдельном потоке
Вот что сделал:
создал процедуру:
создал продедуру для обновления:
На форму бросил Memo1 и Button1, прописал обработчик:
при компиляции получаю ошибку:
Подскажите что не так
Решил читать файл в отдельном потоке
Вот что сделал:
Код: Выделить всё
MonFilesThread = class (TThread)
protected
procedure Execute; override;
public
procedure LogUpdate;
Constructor Create (CreateSuspended: boolean);
private
end;
constructor MonFilesThread.Create(CreateSuspended:boolean);
begin
FreeOnTerminate:=True;
inherited Create(CreateSuspended);
end;
создал процедуру:
Код: Выделить всё
Procedure MonFilesThread.Execute;
var
FilesChange: THandle;
begin
FilesChange := FindFirstChangeNotification(
PChar('test.txt'), //имя файла
false, //не проверяем подкаталоги
FILE_NOTIFY_CHANGE_FILE_NAME+ //создание файла
FILE_NOTIFY_CHANGE_LAST_WRITE); //изменение времени последней записи в файл
try
while not Terminated do
begin
case WaitForSingleObject(FilesChange,1000) of
WAIT_FAILED: Terminate; //Ошибка, завершаем поток
WAIT_OBJECT_0: Synchronize(@LogUpdate); //вызов процедуры обработки файла
end;
FindNextChangeNotification(FilesChange);
end;
finally
FindCloseChangeNotification(FilesChange);
end;
end;
создал продедуру для обновления:
Код: Выделить всё
Procedure MonFilesThread.LogUpdate;
Begin
Memo1.Lines.LoadFromFile('test.txt');
end;
На форму бросил Memo1 и Button1, прописал обработчик:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
StartMonFiles:MonFilesThread;
begin
Memo1.Clear;
if FileExists('test.txt') then Memo1.Lines.LoadFromFile('test.txt');
StartMonFiles:=MonFilesThread.Create(True);
StartMonFiles.Start;
end;
при компиляции получаю ошибку:
Код: Выделить всё
Компиляция проекта, цель: mytread.exe: Код завершения 1, ошибок: 1
unit1.pas(62,3) Error: Identifier not found "Memo1"Подскажите что не так
Погуглите:
1. Область видимости внутри классов (из MonFilesThread не видно напрямую Memo1)
2. Дружественные классы (хотя это тут лишнее, но на будущее)
3. Использование потоков
Нельзя загрузить в визуальный компонент строки, не заблокировав его отрисовку, поскольку отрисовывается контрол из тругого потока, а TStrings не потокобезопасный класс.
1. Область видимости внутри классов (из MonFilesThread не видно напрямую Memo1)
2. Дружественные классы (хотя это тут лишнее, но на будущее)
3. Использование потоков
Нельзя загрузить в визуальный компонент строки, не заблокировав его отрисовку, поскольку отрисовывается контрол из тругого потока, а TStrings не потокобезопасный класс.
Сейчас все нормально, ошибки свои нашел, запустил работает.
Отслеживает если были какие либо изменения в файле, создан или удален файл.
Но блин, сторонний софт пишет в файл и не "закрывает" его, так что изменения не отслеживаются...
По таймеру тоже не прокатит, ибо файл уже открыт и не дает его открыть еще раз. Файл "закроется" только тогда, когда завершит работу программа.
Но как же тогда ФАР его читает?
Отслеживает если были какие либо изменения в файле, создан или удален файл.
Но блин, сторонний софт пишет в файл и не "закрывает" его, так что изменения не отслеживаются...
По таймеру тоже не прокатит, ибо файл уже открыт и не дает его открыть еще раз. Файл "закроется" только тогда, когда завершит работу программа.
Но как же тогда ФАР его читает?
arriah писал(а):Но как же тогда ФАР его читает?
Открывает "только для чтения"?
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
resident, это ладно... notepad++ вполне позволяет открывать и редактировать открытые файлы и отслеживает изменения, позволяя принять или отклонить их.
Лекс Айрин писал(а):notepad++
В EmEditor-е похожая ситуация.
Там кстати есть настройка "Блокировать исходный файл". Но блокировка, насколько я понял, работает с определенного объема файла.
Решил вопрос через TMemoryStream и таймер, примерно так:
вызываю ее по таймеру раз в минуту.
Пока меня устраивает
Код: Выделить всё
procedure TForm1.Button2Click(Sender: TObject);
Var
FMemory:TMomoryStream;
FMemo:TMemo;
i:integer;
begin
FMemory.TMemoryStream.Create;
FMemo:=TMemo.Create(Form1);
FMemo.Visible:=False;
FMemo1.Clear;
FMemory.LoadFromFile('путь_до_занятого_файла\файл.txt'); //делаем копию занятого файла в памяти
FMemo.Lines.LoadFromStream(FMemory); // выгружаем из памяти в Memo
FMemory.Free; //освождаем занятую память
For i=0 to FMemo.Lines.Count-1 do
begin
{ обработка всего что попало в FMemo }
end;
end;вызываю ее по таймеру раз в минуту.
Пока меня устраивает
