Консультация № 171275
12.08.2009, 23:17
0.00 руб.
0 5 2
Здравствуйте уважаемые эксперты. Помогите пожалуйста. Как искать все файлы (скрытые, системные, в системных и скрытых подкаталогах), задавая директорию в которой искать. Вот текст процедуры, которая не хочет искать скрытые файлы. Что можно сделать ?


Приложение:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;

type
TForm1 = class(TForm)
Image1: TImage;
procedure Image1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
SA: Array [1..10000] of String;
N: Longint;

implementation

{$R *.dfm}

procedure ffind(cat: string);
var
sea: TSearchRec;
res: Integer; //результат поиска (0 или нет)
begin
res:=FindFirst(cat+'*.*',faAnyFile,sea); //ищем первый файл
res:=findNext(sea);//ищем следующий файл
While res=0 do
begin
if (Sea.Attr=faDirectory) and ((Sea.Name='.')or(Sea.Name='..')) then//чтобы не было файлов . и..
begin
Res:=FindNext(sea);
Continue;//продолжаем цикл
end;
if (Sea.Attr=faDirectory) then//если нашли директорию, то ищем файлы в ней
begin
Ffind(cat+Sea.Name+'\');//рекурсивно вызываем нашу процедуру
Res:=FindNext(Sea);//ищем след. файл
Continue;//продолжаем цикл
end;
N:=N+1;
SA[N]:=cat+Sea.Name;
Res:=FindNext(Sea);//ищем след. файл
end;
FindClose(Sea);//освобождаем пересенную поиска
end;

end.

Обсуждение

Неизвестный
13.08.2009, 07:14
общий
это ответ
Здравствуйте, Смирнов Михаил Владимирович.

Ваша программа не ищет файлы в скрытых/системных подкаталогах, а не скрытые файлы.
Попробуйте поменять условие сравнения в обоих случаях с вашего (Sea.Attr=faDirectory) на такое (Sea.Attr and faDirectory=faDirectory).
Так как атрибуты файла - это битовая маска, то ваше условие сравнения будет срабатывать только для обычных папок, у которых нет других атрибутов, кроме флага faDirectory, а если у папки есть доп.атрибуты (скрытая, системная и т.д.) - оно работать уже не будет.

С уважением, Дмитрий
Неизвестный
13.08.2009, 09:53
общий
13.08.2009, 20:52
это ответ
Здравствуйте, Смирнов Михаил Владимирович.

Попробуйте заменить if (Sea.Attr=faDirectory) на if (faDirectory in Sea.attr)
Неизвестный
13.08.2009, 13:36
общий
В принципе, Тимошенко Дмитрий уже ответил по существу вопроса, но я бы хотел обратить внмание на некоторые моменты, не относящиеся напрямую к заданному вопросу:

1. В приведённом коде используюся глобальные переменные. Лучше все нужные данные передавать через параметры.
2. Для накопления строк используется статический массив:
- Глобальные переменные использовать нежелательно.
- Даже при их использовании их следовало убрать в раздел implementation
- Не контролируется выход за пределы массива
- Нет возможности увеличить список
- Сам массив, даже не заполненный строками, постоянно занимает память.
Лучше использовать что-то динамическое.
3. Неоптимальное построение цикла: многократное дублирование одних и тех-же операций в разных местах (в частности, вызов FindNext).

Код:
procedure FindFiles(ADir: String; AList: TStrings);
var
sr: TSearchRec;
begin
ADir := IncludeTrailingPathDelimiter(ADir);
if FindFirst(ADir + '*.*', faAnyFile, sr) = 0 then
begin
repeat
if (sr.Attr and faDirectory) <> 0 then // Если каталог
begin
if (sr.Name <> '.') and (sr.Name <> '..') then
FindFiles(ADir + sr.Name, AList);
Continue;
end;
AList.Add(ADir + sr.Name);
until FindNext(sr) <> 0;
FindClose(sr);
end;
end;

const
DirForSearch ='C:\Documents and Settings\All Users';

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.BeginUpdate; // Отключение прорисовки на время обновления
Memo1.Lines.Clear;
FindFiles(DirForSearch, Memo1.Lines);
Memo1.Lines.EndUpdate;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
S: String;
List: TStringList;
begin
List := TStringList.Create;
FindFiles(DirForSearch, List);
if List.Count = 0 then
S := 'Файлов не найдено'
else
S := Format('Найдено файлов: %d'#13#10#13#10'%s'#13#10'...'#13#10'%s',
[List.Count, List[0], List[List.Count-1]]);
ShowMessage(S);
List.Free;
end;
Неизвестный
13.08.2009, 13:56
общий
PaVeL_Ekt:
Попробуйте заменить if (Sea.Attr=faDirectory) на if (faDirectory in Sea.attr)


Sea.Attr - это не множество, а обычный Integer, поэтому следует использовать битовые операции.

TSearchRec = record
Time: Integer;
Size: Int64;
Attr: Integer;
...
Неизвестный
13.08.2009, 15:39
общий
Смирнов Михаил Владимирович странный у вас стиль программирования однако
Впервые вижу в сети такой код.
Советую не проигнорировать очень дельные замечания Gramy
Форма ответа