Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Проверка на изменение файла


Автор: -Mikle- 15.10.2004, 17:06
Кто подскажет, как наилучшим способом можно отследить изменение содержимого текстового файла?

Подробней:
Есть "левый" процесс, который постоянно пишет в этот лог-файл, всегда добавляет туда строки. Скорость записи большая, за сутки - 500Мб(около 350Кб в секунду). Я пишу процесс, который следит за этим файлом, и динамически записывает данные из него в БД.

На данный момент я делаю так:
Так как файл всегда растет в размере и строки которые уже записаны, никогда не меняются, происходит только добавление, то я в цикле отслеживаю размер файла, и при изменении размера провожу добавление куска записей в БД, запоминаю позицию до которой я записал все в БД, и жду следующего изменения размера, и потом опять пишу в БД, начиная с запомненой позиции.

Вот что мне не нравится:
Проверку делаю так
Код
do
  if LOF(hFile)>PrevLen then
     .....
     .....
     PrevLen=LOF(hFile)
  end if
  doevents
  sleep 100
loop


Это криво! Красивей было бы например отслеживать какие-нибудь события(если они есть), которые возникают при изменении файла, или еще чнго нить... как нибудь красивей, оригинальней, алгоритм должен быть быстрым, и не ресурсоемким, так как это будет находиться на серваке Radius.

Какие предложения? Рассмотрю все... спасибо.

Автор: cardinal 15.10.2004, 17:32
Ну во первых конечно надо избавиться от цикла. Читай здесь:
http://forum.vingrad.ru/index.php?showtopic=30085
А ты можешь изменить что-нибудь в том "левом процессе"?

Автор: -Mikle- 15.10.2004, 19:22
Цитата(cardinal @ 15.10.2004, 21:32)
А ты можешь изменить что-нибудь в том "левом процессе"?
если бы мог... было бы все просто... потому и процесс я называю "левый" smile.gif это готовая программа, пишет логи... а мне надо их собирать в БД, чтоб потом обрабатывать

А про Timer я уже думал, это как запасной вариант у меня. Спасибо!
Я просто хотел сделать ваще по другому принципу, не проверять через определенный интервал изменился ли размер файла, а реагировать как нибудь только тогда, когда в файл что-нить записалось. Может хук на систему сделать, есть ли какое-нибудь событие которое сообщает об этом? Наверное есть, потому что как тогда виндовая утилита "Поиск файлов" узнает что гдето в папках произошли изменения? Ишеш файлы по маске, потом, когда поиск уже закончен(!)(но окно поиска открыто), если в любом месте на диске создать файл с именем удовлетворяющим критерию маски, то этот файл сразу же попадает в список найденых в окне поиска. Он же не переискивает заново на всем диске? Поисковик как-то узнает о том, что какой-то файл создали, т.е. изменили содержимое директории... Вот как это сделать?

Автор: cardinal 16.10.2004, 01:46
Цитата(Mikle @ 15.10.2004, 18:22)
А про Timer я уже думал, это как запасной вариант у меня. Спасибо!

Это как ты понимаешь всегда лучше цикла...
Цитата(Mikle @ 15.10.2004, 18:22)
Я просто хотел сделать ваще по другому принципу, не проверять через определенный интервал изменился ли размер файла, а реагировать как нибудь только тогда, когда в файл что-нить записалось.

Ладно... Тогда предожение следующее:
Когда-то слышал, что в Винде крутиться постоянно несколько тысяц процессов. Плюс или минус один процесс разницы не далает. Почему бы не сделать thread который и будет заниматься только тем, что проверять изменился ли файл или нет? Думаю ничего другого придумать нельзя. А когда этот твой процесс обнаружит изменение файла он и пошлет тебе msg, которое ты примешь и сможешь обновить базу...
Вот. Пока ничего другого в голову не приходит.

Автор: -Mikle- 16.10.2004, 08:26
Да, наверное так и придется сделать. Спасибо за предложение кардинал! Тебе плюс за то, что не покинул мой топик, а попытался предложить. Молодец! Если найду чего нибудь оригинальней, то выкину сюда. Но если появятся другие предложения, жду...

Автор: Akina 16.10.2004, 13:13
-Mikle-
Цитата
Проверку делаю так

У тебя еще не было случая когда очередная запись произошла в момент выполнения цикла проверки? Будет...

Код
do
NewLen=LOF(hFile)
if NewLen>PrevLen then
 .....
 .....
 PrevLen=NewLen
end if
doevents
sleep 100
loop


Впрочем это относится к ЛЮБОЙ реализации. Т.е. сразу длину файла - в переменную, и работаешь до следующего опроса ТОЛЬКО с этой переменной, игнорируя изменения файла в процессе обработки - они будут обработаны в следующем цикле.

Автор: -Mikle- 18.10.2004, 00:27
Ну вот, если долго мучаться, что нибудть получится :)

Код
'Это в модуль
Public Declare Function FindFirstChangeNotification Lib "kernel32" Alias "FindFirstChangeNotificationA" (ByVal lpPathName As String, ByVal bWatchSubtree As Long, ByVal dwNotifyFilter As Long) As Long
Public Declare Function FindNextChangeNotification Lib "kernel32" (ByVal hChangeHandle As Long) As Long
Public Declare Function FindCloseChangeNotification Lib "kernel32" (ByVal hChangeHandle As Long) As Long

Public Const FILE_NOTIFY_CHANGE_SIZE = &H8

Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Public Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

Dim hN As Long

Sub WaitForFileChange(ByVal As Long)
  hN = FindFirstChangeNotification("c:\Folder1", 0, FILE_NOTIFY_CHANGE_SIZE)
  Do
     WaitForSingleObject hN, -1
     MessageBox 0, "Размер какого-то файла в папке ''C:\Folder1\'' изменился!", "Hello", 0
     FindNextChangeNotification hN
  Loop
End Sub


Функция WaitForFileChange вызывается в отдельной нити(потоке), разумеется для работы самих ф-ий Find...ChangeNotification это не обязательно, просто для конкретно моей реализации я запустил бесконечный цикл проверки в отдельном потоке. Таким образом я могу реагировать на событие изменение размера какого-то файла в папке. Замечу что событие не привязано к файлу, а ко всей директории, но это не проблема. Можно реализовать проверку на то изменился ли размер нужного мне файла, или нет. Если не изменился, ждать следущих изменений в папке.
Константы
Код
Public Const FILE_NOTIFY_CHANGE_ATTRIBUTES = &H4
Public Const FILE_NOTIFY_CHANGE_DIR_NAME = &H2
Public Const FILE_NOTIFY_CHANGE_FILE_NAME = &H1
Public Const FILE_NOTIFY_CHANGE_LAST_WRITE = &H10
Public Const FILE_NOTIFY_CHANGE_SECURITY = &H100

позволяют отслеживать другие события. Вот так то! :)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)