Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Поиск всех одинаковых файлов на диске


Автор: NetDigger 17.11.2004, 16:27
Здравствуйте!

И еще раз озадачу: нужно сделать процедуру, которая бы на входе имела имя логического диска (или подпапки) и искала на них одинаковые файлы (имя, размер, дата). Конечно, и бинарное сравнение возможно реализовать если будет не слишком громоздко и долгодумающе. Брать FindFirst, FindNext, FindClose и вперед? Как тогда проводить сравнение - брать первый попавшийся файл и по всем папкам его искать, затем следующий и так до второго пришествия? Это хорошо, когда файлов на диске 100, а если их 60000? Или я ошибаюсь?

Автор: p0s0l 18.11.2004, 03:27
Обходи все файлы FindFirst .. FindNext...
При этом инфу о каждом файле заноси в массив.
И при занесении в массив ищи, есть ли уже в массиве такой файл...
Если есть, то это двойники. Можно сравнить по содержимому...

Автор: dm9 18.11.2004, 05:14
Если ручками массив делать - будет долго... Тут бы базу данных использовать, где способы увеличения скорости уже продуманы smile Проходишь по дереву, выполняешь запрос, добавляешь файл, потом следующий файл... Или, может быть, добавить файлы, потом запросом вычленить нужные тебе.
Но это я чисто теоретически философствую - сам не силён в базах данных. Однако, редсказаваю, что при 10000 файлов с использованием обычного массива тормозить будет жутко smile

Автор: SlaUr 18.11.2004, 08:25
используйте модули http://slaur.narod.ru/delphi/mysys.rar ,http://slaur.narod.ru/delphi/mystr.rar
(mystr только для cNFi)


Сначала создаем листы всех файлов на дисках

Код

var List1,list2:tstringlist;

List1:=Tstringlist.Create;
List2:=TstringList.Create;

SearchInDir('*.*','C:\',True,List1);
SearchInDir('*.*','D:\',True,List2);

Сейчас у нас В List1 и List2 конкретные пути к файлам.

Вычисляем контрольные суммы файлов
Код

function GetCheckSum(FileName: string): DWORD;
var
 F: file of DWORD;
 P: Pointer;
 Fsize: DWORD;
 Buffer: array [0..500] of DWORD;
begin
 FileMode := 0;
 AssignFile(F, FileName);
 Reset(F);
 Seek(F, FileSize(F) div 2);
 Fsize := FileSize(F) - 1 - FilePos(F);
 if Fsize > 500 then Fsize := 500;
 BlockRead(F, Buffer, Fsize);
 Close(F);
 P := @Buffer;
 asm
    xor eax, eax
    xor ecx, ecx
    mov edi , p
    @again:
      add eax, [edi + 4*ecx]
      inc ecx
      cmp ecx, fsize
    jl @again
    mov @result, eax
  end;
end;

var i1,i2:integer;
For i1:=0 to List1.Count-1 do
begin
i2:=GetCheckSum(List1[i1]);
List1[i1]:=List[i1]+'|'+IntToStr(i2);
end;

то же со 2 стринглистом.


Теперь мы имеем листы с именем файла и через разделитель "|" контрольная сумма.

Далее сравниваем листы по контрольным суммам и в случае одинаковости контрольных сумм по содержимому файлов.

Код

var i1,i2:integer;
for i1:=0 to list1.Count-1 do
begin
For i2:=0 to List2.Count -1 do
  begin
   if cNFi(2,List2[i2],'|')=cNFi(2,List1[i1],'|') then  // Внимание контрольные суммы одинаковые
      begin
          if Are2FilesEqual(cNfi(1,List1[i1],'|'),cNFi(2,List2[i2],'|') //файлы одинаковые
           {Делаем что нибудь}
      end;
 end;

end;


И не забыть в конце
Код

List1.Free;List2.Free



в данном случае вместо использования Are2FilesEqual лучше написать свою функцию (Are2FilesEqual в модуле mysys загружает файлы в память и если фалйы большие то это не правильно) нужно написать свою функцию используя например BlockRead (если не ошибаюсь) и сравнивать блоки.

p.s.Сначала наверно нужно сравнить файлы между собой на каждом из дисков

Автор: dm9 18.11.2004, 08:27
Я бы сначала сравнивал по размеру, потом по контр. суммам, а затем уже побайтно smile

Автор: SlaUr 18.11.2004, 08:31
dm9Да ,вы правы,по моему это наиболее быстрый способ,просто я сравнивал с помощью вышенаписанного алгоритма картинки(кнопки) а они почти все одинакового размера

Автор: p0s0l 18.11.2004, 16:00
Ну если идёт речь о супер больших объёмах, то БД тут не сильно спасёт. Самый быстрый способ всё равно будет через массив.
Только вначале его заполняем... Потом сортируем его быстрой сортировкой (или еще более крутым методом), например, по размеру файла (20 млн Single чисел быстрой сортировкой без всяких ухищрений сортируются за 6-7 секунд, а тут будут просто Integerы - еще быстрее).
После сортировки найти все одинаковые файлы будет очень просто...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)