![]() |
|
|
|
|
#1
|
|||
|
|||
|
Такая вот ситуация сложилась.
Задача: Небольшая програмка которая бы исполняла роль журнала для файлов. Тоисть мониторила указаную папку и подпапки на наличие файлов удовлетворяющим условие. Должен быть фильтр по маске файла. Например в папке и подпапках есть xml,txt... файли. В програмку помещаеться поле выбора: 1.форматы файлов - заранее прописываються интересующие формати xml,txt например. 2.в имени файла с 5 по 10 символ присутсвует например название склада - нужен фильтр по названию склада. 3.последние 4 символа имени файла - дата документа - нужен фильтр по этой дате. Найденые файли должны отображаться в таблице с возможностью по правому клику на файле выдать контекстное меню с возможностью печати\открытия в блокноте например. Вот такая задачка. Может кто-нить поможет начать ее реализацию, может встречал кто исходники с подобным. Заранее благодарен всем! |
|
#2
|
|||
|
|||
|
Я такое писал, создавал поток который сканит выбранную папку на наличие файлов по заранее известной маске, в зависимости от файла выполняет действия.
модуль потока Код:
unit ScanDir;
interface
uses
Classes, Windows, SysUtils;
type
FParam = record
ID: integer;
Str: string; // путь к директории с файлами
Name: string; // имя потока
FName: string; // маска файла
end;
TScanDir = class(TThread)
public
constructor Create(Param: FParam);
private
protected
P: FParam;
procedure Execute; override;
end;
implementation
uses
main; // модуль с формой
procedure TScanDir.Execute;
var
r: Cardinal;
fn: THandle;
SRec: TSearchRec;
begin
fn := FindFirstChangeNotification(pChar(P.str), True,
FILE_NOTIFY_CHANGE_FILE_NAME);
repeat
r := WaitForSingleObject(fn, 1000);
if r = WAIT_OBJECT_0 then
begin
if FindFirst(P.Str + '\' + P.AName, faAnyFile, SRec) = 0 then
repeat
GlobalThreadID := p.ID; // глобальные переменные
GlobalThreadName := p.Name; // чтобы в статистике знать
GlobalThreadDir := p.Str; // какой поток сработал
GlobalThreadFile := SRec.Name;
Synchronize(Form1.UpdateMemo);
Synchronize(form1.ExtractFile);
until FindNext(SRec) <> 0;
FindClose(SRec);
end;
if not FindNextChangeNotification(fn) then
break;
until Terminated;
FindCloseChangeNotification(fn);
end;
constructor TScanDir.Create(Param: FParam);
begin
inherited Create(true);
P := Param;
end;
end.ну и соответственно запускаешь потоки из основной программы Код:
...
var
ThreadScanDir: TScanDir;
....
ThreadScanDir := TScanDir.Create(Param);
ThreadScanDir.FreeOnTerminate := true;
ThreadScanDir.Priority := tplower;
ThreadScanDir.Resume; |
|
#3
|
|||
|
|||
|
Ну, здесь такое сложное решение даже не нужно. Достаточно просто периодически запускать скан папки с подпапками. Сложнее всего будет с фильтрацией. Если позиции по 2 и 3 пунктам точно фиксированные, то и тут все несложно. Тебе нужны функции FindFirst/FindNext/FindClose и MatchesMask.
Алгоритм примерно такий. В памяти делжим список найденных файлов. Перед поиском его очищаем. Начинаем поиск с корня указанной папки. Если найденный объект есть папка - идем внутрь и рекурсивно вызывем ту же процку. Если файл то: 1. проверяем расширение по маске 2. проверяем номер по позициям в имени файла 3. проверяем дату Если все проверки прошли, то добавляем файл в список. Если нет, то не добавляем. шаблон: Код:
var
FoundFiles : TStringList;
function CheckFile(AFileName : String; AExt : Array Of String; Awarehouse : String; ADate : String) : Boolean;
begin
Result := False;
// Здесь проверяем на соотв. условиям. Лень писать.
// Если все проверки прошли, то Result := True;
end;
procedure DoFindFiles(APath : String; AExt : Array Of String; Awarehouse : String; ADate : String);
var
F : TSearchRec;
iFound : Integer;
begin
iFound := FindFirst(APath + '*.*',faAnyFile,F);
While iFound = 0 Do
Begin
If (F.Attr and faDirectory) <> 0
Then DoFindFiles(APath + F.Name + '\',AExt,AWarehouse,ADate)
Else
If CheckFile(F.Name,AExt,AWarehouse,ADate)
Then FoundFiles.Add(APath + F.Name);
iFound := FindNext(F);
End;
FindClose(F);
end;
proedure FindFiles(APath : String; AExt : Array Of String; Awarehouse : String; ADate : String);
begin
FoundFiles.Clear;
DoFindFiles(APath,AExt,AWarehouse,ADate);
end; |