|
Вопрос # 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.
Ну а поиск файлов на диске - это рекурсивная функция. Вот тебе пример (выдрал из своей старой проги). Там много лишнего, выкинешь сам.
Будут вопросы - обращайся.
Приложение: Переключить в обычный режим- procedure TMainForm.SearchFiles(const Path:string);
- var
- Rec:TSearchRec;
- Finded:Integer;
- NewItem:TListItem;
- Ext:string;
- IconIndex:Integer;
- Icon:TIcon;
- CRC32:Cardinal;
- begin
-
- faReadOnly $00000001 Read-only files
- faHidden $00000002 Hidden files
- faSysFile $00000004 System files
- faVolumeID $00000008 Volume ID files
- faDirectory $00000010 Directory files
- faArchive $00000020 Archive files
- faAnyFile $0000003F Any file
- }
-
- if ProcessCancelled
- then Exit;
- if not DirectoryExists(Path)
- then Exit;
- Icon:=TIcon.Create;
- Finded:=FindFirst(Path+'*.*',faAnyFile,Rec);
- try
- while (Finded=0) and (not ProcessCancelled) do
- begin
- if (Rec.Attr and faVolumeID)<>0
- then Continue;
- if ((FilesFound+DirsFound) mod 100)=0
- then RefreshInfo(Path);
- if (Rec.Attr and faDirectory)<>0
- then begin
- if (Rec.Name<>'.') and (Rec.Name<>'..') and IncludeCheckBox.Checked
- then begin
- Inc(DirsFound);
- SearchFiles(Path+''+Rec.Name);
- end
- end
- else begin
- if MatchesMask(Rec.Name,Mask)
- then begin
- Inc(FilesFound);
- NewItem:=ListView.Items.Add;
- NewItem.Caption:=Rec.Name;
- //NewItem.ImageIndex:=1;
-
- Ext:=ExtractFileExt(Rec.Name);
- IconIndex:=Extentions.IndexOf(Ext);
-
- then NewItem.ImageIndex:=IconIndex+2
-
- else begin
-
- NewItem.ImageIndex:=ImageList.AddIcon(Icon);
- Extentions.Add(Ext);
- end;
-
- NewItem.SubItems.Add(Path);
- NewItem.SubItems.Add(IntToStr(Rec.Size));
- NewItem.SubItems.Add('');
- NewItem.SubItems.Add('');
- if (Rec.Attr and faReadOnly)<>0
- then NewItem.SubItems.Add('+')
- else NewItem.SubItems.Add('');
- if (Rec.Attr and faArchive)<>0
- then NewItem.SubItems.Add('+')
- else NewItem.SubItems.Add('');
- if (Rec.Attr and faHidden)<>0
- then NewItem.SubItems.Add('+')
- else NewItem.SubItems.Add('');
- if (Rec.Attr and faSysFile)<>0
- then NewItem.SubItems.Add('+')
- else NewItem.SubItems.Add('');
- NewItem.SubItems.Add(DateTimeToStr(FileDateToDateTime(Rec.Time)));
- try
- CRC32:=GetFileCRC32(Path+''+Rec.Name);
- NewItem.SubItems.Add(IntToHex(CRC32,8));
- except
-
- end;
- end; // if MatchesMask(Rec.Name,FileNameComboBox.Text)
- end;
- Finded:=FindNext(Rec);
- end; // while
- finally
- FindClose(Rec);
- FreeAndNil(Icon);
- end;
- 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
Ответ #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™ (статус: Доктор наук), 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)
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|