.

Я сам не раз задавался этим вопросом. Например, вот такая ситуация: Вам необходимо написать пакетную обработку файлов. Т.е. пользователь указывает папку в которой, например, располагается куча подпапок с картинками или xml-файлов. И все бы хорошо, но в интернете полно примеров кода, где функция выдает сведения о файлах, которые находятся в папке, которую вы указали. Но подпапки не проверяются на предмет: содержат файлы или нет. Как это исправить?

Здесь я привел свои наработки на данную тему...

Я долго искал ответ, пока не наткнулся на следующий код:

procedure GetAllFiles( Path: string; Lb: TListBox);
var
sRec: TSearchRec;
isFound: boolean;
begin
isFound := FindFirst( Path + '\*.*', faAnyFile, sRec ) = 0;
while isFound do
begin
if ( sRec.Name <> '.' ) and ( sRec.Name <> '..' ) then
begin
if ( sRec.Attr and faDirectory ) = faDirectory then
GetAllFiles( Path + '\' + sRec.Name, Lb );
Lb.Add( Path + '\' + sRec.Name );
end;
Application.ProcessMessages;
isFound := FindNext( sRec ) = 0;
end;
FindClose( sRec );
end;

Код классный, но вот незадача… Есть несколько «НО»:
1. Например, указали папку для поиска ‘C:\Windows\’. В перечень входят пути типа ‘C:\Windows\’ или ‘C:\Windows\System32’. То есть путь к самой папке, которую просматриваем. Я предлагаю модернизировать процедуру, чтобы она в перечисление включала только пути, содержащие ссылку на файлы, например, с расширением ‘.xml’.
2. Все пишется в ListBox... Если вы пишете действительно пакетную обработку, то в 80% случаев вам не надо отображать перечень найденных файлов. Будучи новичком в программировании, в подобной ситуация я бы просто поставил свойство ‘ListBox.Visible:=False;’, тем самым просто скрыл бы компонент. В свое время мне объяснили, что скрытые визуальные объекты есть – ЗЛО 🙂 Потому как они занимают лишнюю память компьютера, хотя вы их не используете по назначению. Исходя из этого золотого правила, я предлагаю сохранять список файлов в TStringList.
И так приступим к модернизации данной функции.

Пункт 1. Для того чтобы выполнить первый пункт, перед добавлением в список файлов нужно просто проверять строку с результатом на вхождение в условие, что путь указывает на файл типа ‘.xml’.

GetAllFiles( Path + '\' + sRec.Name, Lb );
if pos('.xml',copy(sRec.Name, length(sRec.Name)-3,4))=1 then  ///Условие которое добавили, на соответствие первому "НО"
Lb.Add( Path + '\' + sRec.Name );

Пункт 2. Ну, тут все просто, надо иначе прописать компонент, в который будем сохранять список.

procedure GetAllFiles( Path: string; Lb: TStringList); //Здесь заменяем ListBox на TStringList

Важный момент. Если решите использовать другой компонент, обратите внимание на то, каким методом происходит добавление строки. То есть, например, если вы напишите 'TMemo', то вам нужно написать следующее:

Lb.Lines.Add( Path + '\' + sRec.Name );

Ну и напоследок, хотелось бы поделиться еще одной наработкой в этой теме. Пользователь должен указать папку с файлами. Вам не подойдет TOpenDialog, так как он направлен на открытие файла, а нам нужно выбирать папку. Я уже это пробовал и у пользователя это вызывает дискомфорт.
В связи с этим в данной ситуации, я предлагаю использовать функцию SelectDirectory. Вот пример:

Delphi 1-7 : uses FileCtrl;  ///Это дополнительная библиотека которую нужно прописать
Delphi XE : uses vlc.FileCtrl;
procedure GetFileXml;
var
 sql,file_tip:String;
 i:Integer;
 chosenDirectory,adress : string;
begin
  if SelectDirectory('Выберите папку c файлами xml', 'С:\,D:\', chosenDirectory)
  then
  begin
    SL:=TStringList.Create;  //Создаем TStringList
    GetAllFiles(chosenDirectory,SL); //Запускаем функцию сканирования папки
  end
  else
  begin
    exit; //Просто выход из процедуры: если пользователь ничего не выбрал, то не нужно продолжать выполнения процедуры
  end;

 if SL.Count>0  then // Это условие проверяет, есть ли в списке хоть одна ссылка (список не пустой)
 begin
    ProgressOverall.MaxValue:=(SL.Count-1); //Так как обработка у нас пакетная, то хорошо бы отображать процесс в прогресс баре (здесь я использую TGauge, раздел Samples)
 end
 else
 begin
  ShowMessage('Не найдены файлы *.xml! Выберите другую папку.');
  exit;
end;

В своем проекте, я использую два прогресс бара:

- первый отображают общий прогресс – процесс обработки перечня файлов (для этого предназначена строка ProgressOverall.MaxValue:=(SL.Count-1););

- второй – для отображения процесса обработки конкретного xml файла (данная процедура в примере не приведена).
Ну вот я и показал как в delphi можно быстро сформировать список файлов папке, с помощью TSearchRec. Прошу прощения за излишнее «разжевывание» материала. Надеюсь, данная статья будет вам полезна, Дорогие Читатели! С уважением ваш Shinobi.

1 комментарий


  1. Добавление параметра -Rescue к первой описанной команде выводит в списке также содержимое всех вложенных папок.

    Ответить

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *