Помогите.Не могу Понять как будет выглядеть программа после добавления в каждый компонент в процедуру.И после чего всего,как всё будет выглядеть в форме... - вопрос №1007439

Программа dupeGuru2.9.0 также позволяет пользователю настраивать алгоритмы сравнения файлов для более точного поиска, например: типы сканирования, жескость фильтра, заданному слову, разброс похожих слов и другие. При поиске программа выводит список найденных файлов с указанием путей, размеров и процентом совпадения.

Основные возможности:

• Быстрый поиск дубликатов, в том числе среди файлов разных форматов;

• настройка программы под конкретные нужды;

• Безопасность — ни один из нужных файлов не будет удален;

• Функция удаления пустых папок;

• Перемещение и копирование дубликатов, удаление плохих копий.

В этой версии исправлены некоторые ошибки:

• Значительно улучшена скорость и использование памяти при сканировании больших массивов.

• Добавлена поддержка dragdropв панели папок. )

• Исправлена ошибка, приводившая dupeGuruк некорректному отчету при перемещении файлов во время сканирования.

• Прекращена поддержка MacOSX10.4 (Tiger)

 

DupeGuru — небольшая быстрая утилита для поиска дубликатов файлов на компьютере. Интерфейс программы предельно прост: нужно только выбрать область поиска дубликатов (Мои докуметы, все диски, отдельный каталог/типы файлов). Программа просканирует диск и выдаст результат в виде наглядной таблицы. dupeGuruможет просмотреть имена файлов и их содержание. Просмотр имени файла показывает четкий алгоритм соответствия, который может найти двойные имена файла даже когда они не точно похожи.

 

 

Алгоритм:

Производим рекурсивный поиск файлов, по каждому файлу создаем метку = "<имя_файла>:<размер>:<дата>", и сохраняем в бинарное дерево поиска, если такой метки нет, создаем новую, иначе найдены совпадения.

Реализация

Все операции необходимо выполнять в потоке.

type

  TFileSearchThread = class(TThread)

  private

    _TickCountIntervalBeforeRefresh: integer;

    locProgressMax: integer;

    locProgressPosition: integer;

    locSearchFilesDone: integer;

    locCurrentFile: string;

    procedure SetName;

    procedure SetStatus;

    procedure ThreadDone;

    procedure FindFiles(

        paramFolder,

        paramMask: string;

        const paramLevel: integer);

    function GetFilesCount(

        paramFolder: string;

        const paramLevel :integer): integer;

    procedure AddToTree(

        var paramNode: TSearchTreeNode;

        const paramPath: string;

        const paramHash: string;

        const FileSize: integer

        );

  protected

    procedure Execute; override;

  public

    SearchFolder: string;

    Mask: string;

    FilesTree: TSearchTreeNode;

  end;

{$IFDEF MSWINDOWS}

type

  TThreadNameInfo = record

    FType: LongWord;     // must be 0x1000

    FName: PChar;        // pointer to name (in user address space)

    FThreadID: LongWord; // thread ID (-1 indicates caller thread)

    FFlags: LongWord;    // reserved for future use, must be zero

  end;

{$ENDIF}

{ TFileSearchThread }

procedure TFileSearchThread.SetName;

{$IFDEF MSWINDOWS}

var

  ThreadNameInfo: TThreadNameInfo;

{$ENDIF}

begin

{$IFDEF MSWINDOWS}

  ThreadNameInfo.FType := $1000;

  ThreadNameInfo.FName := 'FileSearchThread';

  ThreadNameInfo.FThreadID := $FFFFFFFF;

  ThreadNameInfo.FFlags := 0;

  try

    RaiseException( $406D1388, 0, sizeof(ThreadNameInfo) div sizeof(LongWord), @ThreadNameInfo );

  except

  end;

{$ENDIF}

end;

procedure TFileSearchThread.Execute;

begin

  SetName;

  // Calculate less 2 sec

  _TickCountIntervalBeforeRefresh := GetTickCount()+2000;

  locProgressMax := 0;

  locProgressPosition := 0;

  GetFilesCount(SearchFolder, 0);

  // Start search

  _TickCountIntervalBeforeRefresh := 0;

  findfiles(SearchFolder, Mask, 0);

  // finish

  synchronize(ThreadDone);

end;

Рекурсивный поиск файлов

procedure TFileSearchThread.FindFiles(

      paramFolder,

      paramMask: string;

      const paramLevel: integer);

var

  searchrec: tsearchrec;

  findresult: integer;

  hash: string;

begin

  if self.Terminated then

    exit;

  if paramLevel <= uConst.cLevelCountForCalculateFilesCount then

    Inc(locProgressPosition);

  if locProgressPosition > locProgressMax then

    locProgressMax := locProgressPosition;

  // Update status

  if GetTickCount() > _TickCountIntervalBeforeRefresh then

  begin

    //300 — update thread info interval in msec :

    _TickCountIntervalBeforeRefresh := GetTickCount() + 300; //

    locCurrentFile := paramFolder;

    synchronize(SetStatus);

  end;

  paramFolder:=includetrailingbackslash(paramFolder);

  findresult:=findfirst(paramFolder+paramMask, faanyfile, searchrec);

  try

    while findresult = 0 do

    begin

      if (searchrec.attr and fadirectory)<>0 then

      begin

        if (searchrec.name<>'.') and (searchrec.name<>'..') then

          findfiles(paramFolder+searchrec.name, paramMask, paramLevel+1);

      end

      else

      begin

        hash := searchrec.name;

        hash := hash + ':S'+IntToStr(searchrec.Size);

        hash := hash + ':T'+IntToStr(searchrec.Time);

        AddToTree(FilesTree,paramFolder+searchrec.name,hash,searchrec.Size);

      end;

      findresult:=findnext(searchrec);

    end;

  finally

    findclose(searchrec);

  end;

end;

Сохраняем метку файла в бинарное дерево поиска

procedure TFileSearchThread.AddToTree(

        var paramNode: TSearchTreeNode;

        const paramPath: string;

        const paramHash: string;

        const FileSize: integer

        );

begin

  if not Assigned(paramNode) then

  begin

    paramNode := TSearchTreeNode.Create(nil);

    paramNode.Hash := paramHash;

    paramNode.Files := paramPath+'|'+IntToStr(FileSize);

    paramNode.FilesCount := 1;

  end

  else

  begin

    if paramHash > paramNode.Hash then

      AddToTree(paramNode.HiNode,paramPath,paramHash,FileSize)

     else

    if paramHash < paramNode.Hash then

      AddToTree(paramNode.LowNode,paramPath,paramHash,FileSize)

     else

    begin

      paramNode.FilesCount := paramNode.FilesCount + 1;

      paramNode.Files := paramNode.Files + #13#10+ paramPath+'|'+IntToStr(FileSize);

      // count of entry duplicate files

      if paramNode.FilesCount = 2 then

        Inc(locSearchFilesDone);

    end;

  end;

end;

Предварительное определение общего количества файлов

Для удобства UI, а именно для отображения ProgressBar, нам необходимо приблизительно оценить общее количество файлов, для этого мы рекурсивно подсчитываем число каталогов с вложенностью 2-3(задаем параметром в конфигурационном фале).

functionTFileSearchThread.GetFilesCount(

     paramFolder: string;

     const paramLevel :integer): integer;

var

  searchrec: tsearchrec;

  findresult: integer;

  hash: string;

begin

  // Get folder count in hi 5 levels

  if GetTickCount() > _TickCountIntervalBeforeRefresh then

    exit;

  if paramLevel > uConst.cLevelCountForCalculateFilesCount then

    exit;

  if self.Terminated then

    exit;

  Inc(locProgressMax);

    

  paramFolder := includetrailingbackslash(paramFolder);

  findresult:=findfirst(paramFolder+'*.*', faanyfile, searchrec);

  try

    while findresult = 0 do

    begin

      if (searchrec.attr and fadirectory)<>0 then

      begin

        if (searchrec.name<>'.') and (searchrec.name<>'..') then

          GetFilesCount(paramFolder+searchrec.name, paramLevel+1);

      end;

      findresult:=findnext(searchrec);

    end;

  finally

    findclose(searchrec);

  end;

end;

Ответов пока нет
Посмотреть всех экспертов из раздела Технологии > Delphi
Пользуйтесь нашим приложением Доступно на Google Play Загрузите в App Store