233 / 95 / 15
Регистрация: 31.12.2009
Сообщений: 224

Слежение за каталогом

04.03.2010, 14:51. Показов 5352. Ответов 8
Метки нет (Все метки)

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

Хотелось бы понять получше принцип работы ф-ии ReadDirectoryChangesW, т.к. иногда она не записывает в буфер произошедшие события, например когда в каталог приходит сразу много файлов.

Код потока, слкдящего за каталогом прилагается. Буду очень признателен за добрый совет

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
unit FileMonitorThreadUnit;
 
interface
 
uses
  Classes, Windows, SysUtils;
 
type
  TFileNotifyInformation = packed record
    NextEntryOffset: DWORD;
    Action: DWORD;
    FileNameLength: DWORD;
    FileName: WideChar;
  end;
 
  PFileNotifyInformation = ^TFileNotifyInformation;
 
  TFileEvent = procedure (const FileName: string) of object;
 
  // ïîòîê äëÿ ñëåæåíèÿ çà ïîÿâëåíèåì ôàéëîâ â äèðåêòîðèè
  TFileMonitorThread = class(TThread)
  private
    // äèðåêòîðèÿ äëÿ ñëåæåíèÿ
    FMonitoringDir: string;
    // òåêóùèé îáðàáàòûâàåìûé ôàéë
    FCurrFileName: string;
 
    FOnAddFile: TFileEvent;
    FOnRemoveFile: TFileEvent;
    FOnError: TNotifyEvent;
 
  protected
    // ôàéë ïðèíÿò
    procedure DoAddFile;
    // ôàéë óäàë¸í
    procedure DoRemoveFile;
    // ôàéë ìîäèôèöèðîâàí
    procedure DoModifyFile;
    // îøèáêà!
    procedure DoError;
    procedure Execute; override;
  public
    constructor Create(const MonitoringDir: string; CreateSuspended: Boolean;
      WatchSubTree: Boolean = False);
    property OnAddFile: TFileEvent read FOnAddFile write FOnAddFile;
    property OnRemoveFile: TFileEvent read FOnRemoveFile write FOnRemoveFile;
    property OnError: TNotifyEvent read FOnError write FOnError;
  end;
 
implementation
 
uses
  FormMainUnit;
 
{ TFileMonitorThread }
 
constructor TFileMonitorThread.Create(const MonitoringDir: string;
  CreateSuspended: Boolean; WatchSubTree: Boolean = False);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FMonitoringDir := MonitoringDir;
  if not CreateSuspended then Resume;
end;
 
procedure TFileMonitorThread.Execute;
var
  DirHandle: Cardinal;
  Buffer: Pointer;
  BytesReturn: Cardinal;
  LocalFileName: PWideChar;
  CurrPtr: PFileNotifyInformation;
 
  DirEvent: Cardinal;
  Ovr: OVERLAPPED;
  Events: array [0..1] of Cardinal;
  WaitResult: Cardinal;
const
  FILE_LIST_DIRECTORY = $01;
  BUF_SIZE = (SizeOf(TFileNotifyInformation) + MAX_PATH * 2) * 32;
 
begin
 
  DirHandle := CreateFile(PChar(FMonitoringDir), FILE_LIST_DIRECTORY,
    FILE_SHARE_READ or FILE_SHARE_DELETE or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);
 
  if DirHandle = INVALID_HANDLE_VALUE then
  begin
    FormMain.Log.Write('ÎØÈÁÊÀ! Íå óäàëîñü ïîëó÷èòü äîñòóï ê ïàïêå "' +
      FMonitoringDir + '"');
    Exit;
  end;
 
  // ñîçäà¸ì îáúåêò ñèíõðîíèçàöèè äëÿ ðàáîòû ô-èè ReadDirectoryChangesW
  DirEvent := CreateEvent(nil, True, False, nil);
 
  GetMem(Buffer, BUF_SIZE);
 
  while not Terminated do
  begin
    ZeroMemory(Buffer, BUF_SIZE);
    ZeroMemory(@Ovr, SizeOf(Ovr));
 
    // ïåðåäà¸ì event â ñòðóêòóðó
    Ovr.hEvent := DirEvent;
 
    // âåøàåì îáðàáîòêó òîëüêî íà èçìåíåíèå ôàéëà
    if ReadDirectoryChangesW(DirHandle, Buffer, BUF_SIZE, True,
         FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_SIZE,
         @BytesReturn,
         @Ovr, nil) then
{
    if ReadDirectoryChangesW(DirHandle, Buffer, BUF_SIZE, False,
      FILE_NOTIFY_CHANGE_FILE_NAME, @BytesReturn, nil, nil) then
      }
 
    Events[0] := FormMain.FTerminateEvent;
    Events[1] := DirEvent;
    WaitResult := WaitForMultipleObjects(2, @Events, False, 1000);
 
    case WaitResult of
      WAIT_OBJECT_0: Terminate;
      WAIT_OBJECT_0 + 1:
      begin
        CurrPtr := Buffer;
 
        repeat
          // ïåðåìåùàåì óêàçàòåëü íà ñëåäóþùóþ çàïèñü â ñòðóêòóðå PFileNotifyInformation
          Inc(Cardinal(CurrPtr), CurrPtr^.NextEntryOffset);
 
          // ïîäãîòàâëèâàåì ïåðåìåííóþ FileName äëÿ ïðè¸ìà ñòðîêè
          GetMem(LocalFileName, CurrPtr^.FileNameLength + 2);
          ZeroMemory(LocalFileName, CurrPtr^.FileNameLength + 2);
 
          // êîïèðóåì
          LstrcpynW(LocalFileName, @CurrPtr^.FileName, CurrPtr^.FileNameLength div 2 + 2);
 
          // êîíâåðòèðóåì è çàïîìèíàåì äëÿ îáðàáîòêè èìÿ ôàéëà
          
          FCurrFileName := LocalFileName;
          case CurrPtr.Action of
            FILE_ACTION_ADDED: Synchronize(DoAddFile);
            FILE_ACTION_REMOVED: Synchronize(DoRemoveFile);
            FILE_ACTION_MODIFIED: Synchronize(DoModifyFile);
          end;
          FreeMem(LocalFileName);
 
        until CurrPtr^.NextEntryOffset = 0;
      end;
    end;
  end;
 
  FreeMem(Buffer);
  CloseHandle(DirHandle);
end;
 
procedure TFileMonitorThread.DoAddFile;
begin
  if Assigned(FOnAddFile) then
    FOnAddFile(FMonitoringDir + FCurrFileName);
end;
 
procedure TFileMonitorThread.DoRemoveFile;
begin
  if Assigned(FOnRemoveFile) then
    FOnRemoveFile(FMonitoringDir + FCurrFileName);
end;
 
procedure TFileMonitorThread.DoModifyFile;
begin
end;
 
procedure TFileMonitorThread.DoError;
begin
  if Assigned(FOnError) then FOnError(nil);
end;
 
end.
Добавлено через 18 часов 55 минут
Похоже советов не предвидится. Это не страшно, т.к. съев пуд соли и пролив ведро крови, задачу я решил.

Мог бы рассказать много интересного и привести свой рабочий код если кому-то нужно. Пишите
1
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.03.2010, 14:51
Ответы с готовыми решениями:

Работа с каталогом
Разработать пакетный файл для перехода студента в личный каталог. Группа выбирается из меню, курс передается в командной строке

Сайт с каталогом
Есть авто сайт со своим контентом. Хочу поставить каталог ссылок. Ссылки наверно будут белыми. Так вот вопрос: если яше каталог не...

вариант с каталогом.
Есть сайт "сайт.ru" надо приципить на него каталог ссылок.. ставить на сам сайт не хочу... если сделать субдомен...

8
Добрый самаритянин
 Аватар для John_Pa9JIbHuK
1107 / 622 / 139
Регистрация: 31.03.2009
Сообщений: 2,567
04.03.2010, 14:55
всмысле твоя прога проверяет появились ли новые файлы в каталоге?
0
 Аватар для Mawrat
13113 / 5894 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
04.03.2010, 16:09
Чёрный Медведь, я писал подобную прогу несколько лет назад. Правда на Си.
Отслеживал папку, вновь пришедшие файлы складывал в Оракловую базу. В папку, как раз, записывалось сразу по многу файлов. Я там использовал 2 потока с синхронизацией на мьютексах. - Первый следит за папкой. При обнаружении новых файлов - копирует сведения о новых файлах в FIFO буфер и шлёт сообщение второму потоку. Второй поток ждёт сообщений от первого потока, по их приходу, обрабатывает FIFO буфер и пишет новые файлы в базу. Доступ двух потоков к FIFO буферу регулировался через мьютекс.
Сегодня вечером поищу тот проект...
1
233 / 95 / 15
Регистрация: 31.12.2009
Сообщений: 224
04.03.2010, 17:52  [ТС]
John_Pa9JIbHuK, да что то вроде того

Mawrat, спасибо за предложенную помощь. Полагаю, что с задачей справился, по-этому Ваши исходники не потребуются. Хотел бы добавить, что проблема была в том, что я не проверял валидность файла на момент возникновения события "появился новый файл" и как следствие получал ошибку доступа+тормоза в следящем потоке, из-за которых следующие события вообще могли не обработаться.
В итоге я остановился на том, что юзаю ReadDirectoryChangesW в асинхронном режиме + WaitForMultipleObjects для обеспечения корректного управления завершением следящего потока из основного(через Event). А для копирования файла использую 3-й поток, который проверяет доступ к файлу и как только доступ появляется, делает свою работу.

Если кому то что то непонятно, спрашивайте. Многопоточность - тема достаточно интересная для новичков.
2
0 / 0 / 0
Регистрация: 11.05.2010
Сообщений: 3
11.05.2010, 14:59
Чёрный Медведь, а можно подсмотреть исходники? А то совсем тяжело разобраться с потоками и файлами...
0
233 / 95 / 15
Регистрация: 31.12.2009
Сообщений: 224
11.05.2010, 16:35  [ТС]
_Dem0N,
Можно, конечно )). Однако для целостности картины придётся бросить весь проект. Не пугайтесь что не определяются компоненты, они моего собственного изготовления и касаются только интерфейса. Замените их на стандартные (или удалите совсем) и всё будет компилиться. Удачи Вам. Если будут вопросы, пишите
1
0 / 0 / 0
Регистрация: 11.05.2010
Сообщений: 3
11.05.2010, 16:46
Чёрный Медведь, а исходники вы куда-нибудь выложили на файлообменник или в посте они есть? Просто я не вижу где они...
0
233 / 95 / 15
Регистрация: 31.12.2009
Сообщений: 224
11.05.2010, 17:04  [ТС]
Лучший ответ Сообщение было отмечено как решение

Решение

Пардоньте, я подумал, что уже выложил проект. Заработался...
11.05.2010_16-28 FileReplicator.rar
2
0 / 0 / 0
Регистрация: 11.05.2010
Сообщений: 3
11.05.2010, 17:09
Чёрный Медведь, спасибо огроменное!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.05.2010, 17:09
Помогаю со студенческими работами здесь

Траблы с каталогом
и вообще не все рубрики работают (например на внутреннюю страницу подраздела можно зайти, а сама подрубрика тоже 404 кажет), или только у...

Работа с каталогом
В каталоге, где находится *.EXE файл программы находится некоторое кол-во *.TXT файлов. Задача такова, надо просканировать директорию и...

Работа с каталогом файлов
Очень нужна помощь!!! Надо написать курсовую, а у меня с Си++ очень большие проблемы :( Задача такова : есть каталог изображений...

работа с каталогом Daos
есть C API программа которая работает с файлами в каталоге daos domino 8.5.2 x86, win 2008r2 x64 каталог открываеться станадртной...

Заполнение TreeView небольшим каталогом
Вопрос заключается в заполнении TreeView, как заполнить узел(имя папки) файлами. Папок к примеру 4 шт и в каждой папке свои файлы. Вот...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

Новые блоги и статьи
Система статов в Unity
GameUnited 20.04.2025
Статы — фундаментальный элемент игрового дизайна, который определяет характеристики персонажей, предметов и других объектов в игровом мире. Будь то показатель силы в RPG, скорость передвижения в. . .
Статические свойства и методы в TypeScript
run.dev 20.04.2025
TypeScript прочно занял своё место в системе современной веб-разработки. Этот строго типизированный язык программирования не просто расширяет возможности JavaScript — он делает разработку более. . .
Batch Transform и Batch Gizmo Drawing API в Unity
GameUnited 20.04.2025
В мире разработки игр и приложений на Unity производительность всегда была критическим фактором успеха. Создатели игр постоянно балансируют между визуальной привлекательностью и плавностью работы. . .
Звук в Unity: Рандомизация с Audio Random Container
GameUnited 20.04.2025
В современных играх звуковое оформление часто становится элементом, который либо полностью погружает игрока в виртуальный мир, либо разрушает атмосферу за считанные минуты. Представьте: вы исследуете. . .
Максимальная производительность C#: Советы, тестирование и заключение
stackOverflow 20.04.2025
Погружение в мир микрооптимизаций C# открывает перед разработчиком целый арсенал мощных техник. Но как определить, где и когда их применять? Ответ начинается с точных измерений и профилирования. . . .
Максимальная производительность C#: Предсказание ветвлений
stackOverflow 20.04.2025
Третий ключевой аспект низкоуровневой оптимизации — предсказание ветвлений. Эта тема менее известна среди разработчиков, но её влияние на производительность может быть колоссальным. Чтобы понять. . .
Максимальная производительность C#: Векторизация (SIMD)
stackOverflow 20.04.2025
Помимо работы с кэшем, другим ключевым аспектом низкоуровневой оптимизации является векторизация вычислений. SIMD (Single Instruction, Multiple Data) позволяет обрабатывать несколько элементов данных. . .
Максимальная производительность C#: Процессорный кэш
stackOverflow 20.04.2025
Знакомство с внутренним устройством процессорного кэша — ключевой шаг в написании по-настоящему быстрого кода на C#. Этот слой архитектуры компьютера часто ускользает от внимания разработчиков, но. . .
Максимальная производительность C#: Введение в микрооптимизации
stackOverflow 20.04.2025
В мире разработки на C# многие привыкли полагаться на . NET Runtime, который "магическим образом" сам оптимизирует код. И часто это работает - современные JIT-компиляторы творят чудеса. Но когда речь. . .
MVC фреймворк в PHP
Jason-Webb 19.04.2025
Архитектурный паттерн Model-View-Controller (MVC) – это не просто модный термин из мира веб-разработки. Для PHP-программистов это фундаментальный подход к организации кода, который радикально меняет. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru