Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 537

/ вопрос решён /

Здравствуйте, уважаемые эксперты!Помогите организовать поиск одинаковых файлов,хранящихся в различных каталогах.Никакие имена файлов или каталогов не задаются-поиск ведется по всем доступным логическим дискам !!Зарание БЛАГОДАРЮ!!!!

Черников Артем Николаевич Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: Черников Артем Николаевич (статус: Посетитель)
Вопрос отправлен: 27 апреля 2007, 12:09
Состояние вопроса: решён, ответов: 3.

Ответ #1. Отвечает эксперт: min@y™

Для начала следует определить диски, на которых надо вести поиск. Здесь поможет функция GetDriveType() + халп по ней.

The GetDriveType function determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.

UINT GetDriveType(
LPCTSTR lpRootPathName // address of root path
);


Parameters

lpRootPathName

Points to a null-terminated string that specifies the root directory of the disk to return information about. If lpRootPathName is NULL, the function uses the root of the current directory.



Return Values

The return value specifies the type of drive. It can be one of the following values:

Value Meaning
0 The drive type cannot be determined.
1 The root directory does not exist.
DRIVE_REMOVABLE The drive can be removed from the drive.
DRIVE_FIXED The disk cannot be removed from the drive.
DRIVE_REMOTE The drive is a remote (network) drive.
DRIVE_CDROM The drive is a CD-ROM drive.
DRIVE_RAMDISK The drive is a RAM disk.

Ну а поиск файлов на диске - это рекурсивная функция. Вот тебе пример (выдрал из своей старой проги). Там много лишнего, выкинешь сам.

Будут вопросы - обращайся.

Приложение:
  1. procedure TMainForm.SearchFiles(const Path:string);
  2. var
  3. Rec:TSearchRec;
  4. Finded:Integer;
  5. NewItem:TListItem;
  6. Ext:string;
  7. IconIndex:Integer;
  8. Icon:TIcon;
  9. CRC32:Cardinal;
  10. begin
  11.  
  12. faReadOnly $00000001 Read-only files
  13. faHidden $00000002 Hidden files
  14. faSysFile $00000004 System files
  15. faVolumeID $00000008 Volume ID files
  16. faDirectory $00000010 Directory files
  17. faArchive $00000020 Archive files
  18. faAnyFile $0000003F Any file
  19. }
  20.  
  21. if ProcessCancelled
  22. then Exit;
  23. if not DirectoryExists(Path)
  24. then Exit;
  25. Icon:=TIcon.Create;
  26. Finded:=FindFirst(Path+'*.*',faAnyFile,Rec);
  27. try
  28. while (Finded=0) and (not ProcessCancelled) do
  29. begin
  30. if (Rec.Attr and faVolumeID)<>0
  31. then Continue;
  32. if ((FilesFound+DirsFound) mod 100)=0
  33. then RefreshInfo(Path);
  34. if (Rec.Attr and faDirectory)<>0
  35. then begin
  36. if (Rec.Name<>'.') and (Rec.Name<>'..') and IncludeCheckBox.Checked
  37. then begin
  38. Inc(DirsFound);
  39. SearchFiles(Path+''+Rec.Name);
  40. end
  41. end
  42. else begin
  43. if MatchesMask(Rec.Name,Mask)
  44. then begin
  45. Inc(FilesFound);
  46. NewItem:=ListView.Items.Add;
  47. NewItem.Caption:=Rec.Name;
  48. //NewItem.ImageIndex:=1;
  49.  
  50. Ext:=ExtractFileExt(Rec.Name);
  51. IconIndex:=Extentions.IndexOf(Ext);
  52.  
  53. then NewItem.ImageIndex:=IconIndex+2
  54.  
  55. else begin
  56.  
  57. NewItem.ImageIndex:=ImageList.AddIcon(Icon);
  58. Extentions.Add(Ext);
  59. end;
  60.  
  61. NewItem.SubItems.Add(Path);
  62. NewItem.SubItems.Add(IntToStr(Rec.Size));
  63. NewItem.SubItems.Add('');
  64. NewItem.SubItems.Add('');
  65. if (Rec.Attr and faReadOnly)<>0
  66. then NewItem.SubItems.Add('+')
  67. else NewItem.SubItems.Add('');
  68. if (Rec.Attr and faArchive)<>0
  69. then NewItem.SubItems.Add('+')
  70. else NewItem.SubItems.Add('');
  71. if (Rec.Attr and faHidden)<>0
  72. then NewItem.SubItems.Add('+')
  73. else NewItem.SubItems.Add('');
  74. if (Rec.Attr and faSysFile)<>0
  75. then NewItem.SubItems.Add('+')
  76. else NewItem.SubItems.Add('');
  77. NewItem.SubItems.Add(DateTimeToStr(FileDateToDateTime(Rec.Time)));
  78. try
  79. CRC32:=GetFileCRC32(Path+''+Rec.Name);
  80. NewItem.SubItems.Add(IntToHex(CRC32,8));
  81. except
  82.  
  83. end;
  84. end; // if MatchesMask(Rec.Name,FileNameComboBox.Text)
  85. end;
  86. Finded:=FindNext(Rec);
  87. end; // while
  88. finally
  89. FindClose(Rec);
  90. FreeAndNil(Icon);
  91. end;
  92. end;


Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 27 апреля 2007, 13:19
Оценка за ответ: 5

Ответ #2. Отвечает эксперт: Матвеев Игорь Владимирович

Здравствуйте, Черников Артем Николаевич!
При сканировании заполняете базу данных вида:

Имя файла и путь | Размер | Хэш сумма

Хэш сумма - либо CRC (CRC32), либо md5, либо еще что-то, алгоритмов много, они свободно доступны в сети, нужно выбирать из соображений быстродействия.

База данных, это условно, может быть и список или просто массив.

Далее ищите в базе записи с одинаковым размером и одинаковой Хеш суммой. Ну и, если это требуется сверяете побайтово, либо с помощью более 'длинного' хеша.

Ссылки по теме:
- CRC32 - www.delphiworld.nqrod.ru/base/32_bits_crc.html (обнажды я проводил тестирование алгоритмов вычисления CRC32 - этот оказался самым быстрым);
- MD5 - www.delphiworld.nqrod.ru/base/md5.html

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Время отправки: 27 апреля 2007, 13:29
Оценка за ответ: 5

Ответ #3. Отвечает эксперт: Denisss

Я бы делал так:
1. Создал бы два потока - один для поиска файлов, другой для расчета контрольной суммы (CRC32);
Алгоритмов поиска файлов и расчета CRC32 (его я бы выбрал благодаря его быстродействию) в интернете полно.

2. По нажатию на кнопку, запускаются оба потока - один ищет файлы, другой ждет когда первый найдет файл и расчитывает его контрольную сумму (лучше всего будет, если расчет будет проводиться не для всего файла, а, например, для первых или последних 256 байт, либо 128 первых + 128 последних и т.д.). Кнопка эта блокируется, либо преобразуется в кнопку "Отмена". Первый поток передает данные второму: Путь к файлу, его размер. Файлы размером 0 байт игнорируются (возможно, игнорируются и другие маленькие файлы).

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

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

PPS
Все описанное выше - лишь мое представление о том, как бы я реализовал поиск файлов-дубликатов.

Ответ отправил: Denisss (статус: 2-ой класс)
Время отправки: 27 апреля 2007, 16:05
Оценка за ответ: 4


Мини-форум вопроса

Всего сообщений: 1; последнее сообщение — 27 апреля 2007, 13:38; участников в обсуждении: 1.
min@y™

min@y™ (статус: Доктор наук), 27 апреля 2007, 13:38 [#1]:

Если надо искать одинаковые файлы, то в приведённой процедуре производится вычисление CRC32 каждого найденного файла. Эти CRC32 можно запихать в TStringList.Objects вместе с именами и отсортировать. Дальше - дело техники. Целиком вставить эту функцию сюда не получилось. Могу выслать или скачай пакет модулей Delphi Works.

Можно вместо CRC32-суммы юзать MD5-хэш. Если надо, могу прислать и эту функцию. Или качай вот отсюда: http://www.torry.net/vcl/security/strong/dmmd5.zip
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

31 января 2011, 20:00: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:39
Выполнено за 0.03 сек.