Обход дерева папок с построением списка файлов

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Обход дерева папок с построением списка файлов

Сообщение trengtor » 05.07.2013 19:39:14

Subj. Нет ли где готовых вариантов?
(Windows-платформа, если это критично)
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Обход дерева папок с построением списка файлов

Сообщение alexs » 05.07.2013 22:47:15

А в чём проблема?
FindFirst+FindNext и рекурсия вам в руки...

Добавлено спустя 1 минуту 10 секунд:
Если интересно - в RX есть даже компонент, который строит в указанном пункте меню программы иерархическое дерево по содержимому каталога...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Обход дерева папок с построением списка файлов

Сообщение rxt » 10.07.2013 15:06:00

alexs писал(а):А в чём проблема?
FindFirst+FindNext и рекурсия вам в руки...

Будьте же цивилизованы,
Пространство имён (Shell namespace) оболочки Windows является древовидной структурой ....
IShellFolder.EnumObjects создает объект для перечисления идентификаторов, с помощью интерфейса которого можно перечислять содержимое папки.
Более подробную информацию спрашивать у ОРАКУЛА.

Пример:
Код: Выделить всё
program PrintFolders;
{$APPTYPE CONSOLE}
{$mode Delphi}{$H+}

{ Консольное приложение выводит дерево папок
c помощью пространства имён оболочки Windows.}


uses
  Windows, SysUtils,ActiveX, ShlObj, ComObj;

const
  SHCONTF_FOLDERS = $20;
  SHCONTF_NONFOLDERS = $40;
  SHCONTF_INCLUDEHIDDEN = $80;
  SHGDN_NORMAL  = $0;
  SHGDN_INFOLDER  = $1;
  SHGDN_INCLUDE_NONFILESYS = $2000;

//------------------------------------------------------------------------------
{ вывод в консоль}
procedure AppendLog(const Text: string);
var
  s:string;
begin
  SetLength(s, Length(text));
  if not CharToOemA(PChar(text), PChar(s)) then s := text;
  WriteLn(s);
end;


//------------------------------------------------------------------------------
{ сдвигаем вывод для отображения иерархии }
procedure WriteLevel(Count: Integer);
var
  s: string;
begin
  s := StringOfChar(' ', Count);
  Write( s );
end;


var
  Malloc: IMalloc;
  desktop, InitShellDir: IShellFolder;
  pidlItself: PItemIDList;
  Level, CountFolder: Integer;
  CharsDone, dwAttributes, StartTime:DWORD;
  InitPath:WideString;

//------------------------------------------------------------------------------
{ получаем имя }
function GetDisplayName( pidl: PItemIDList; const STRT: STRRET ): string;
var
  P:PChar;
begin
  with STRT do
  case uType of
    STRRET_CSTR   : SetString(Result, STRT.cStr,   Length(STRT.cStr));
    STRRET_OFFSET : begin
                       P  := @PiDL.mkid.abID[STRT.uOffset - SizeOf(PiDL.mkid.cb)];
                       SetString(Result, P, PIDL.mkid.cb - STRT.uOffset);
                    end;
    STRRET_WSTR   : begin
                       Result     :=  STRT.pOleStr;
                       Malloc.Free(STRT.pOleStr);
                    end;
    end;
end;



//------------------------------------------------------------------------------
{ основная процедура обхода дерева вызывается рекурсивно }
procedure ShowFolder(folder: IShellFolder);
var
  pidlChild: PItemIDList;
  STRT: STRRET;
  Iterator: IEnumIDList;
  celtFetched: ULONG;
  child: IShellFolder;
begin
  OleCheck(folder.EnumObjects( 0 , SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN, Iterator ));
  try
    Inc(Level);
    While Iterator.Next( 1, pidlChild, celtFetched ) = NOERROR do
      try
        Olecheck(folder.GetDisplayNameOf( pidlChild, SHGDN_INFOLDER or SHGDN_INCLUDE_NONFILESYS, STRT ));
        WriteLevel(Level );
        Inc(CountFolder);
        AppendLog( GetDisplayName( pidlChild, STRT ) );
        OleCheck(folder.BindToObject( pidlChild, nil, IID_IShellFolder, Pointer(child) ));
        try
        ShowFolder( child );
        except
          // обработак ошибок
          on E:EOleException do
            AppendLog('***** EOleException:  [$'+IntToHex(E.ErrorCode, 8)+'] '+E.Message);
          on E:Exception do
            AppendLog('***** Exception: [$'+IntToHex(GetLastError, 8)+'] '+E.Message);
        end;
        child := nil;
      finally
        Malloc.Free( pidlChild );
      end;
  finally
    Dec(Level);
  end;
end;



//==============================================================================
{  НАЧАЛО }
begin
  if Paramcount > 0 then
    InitPath := ParamStr(1) else
    InitPath := ExtractFilePath(ParamStr(0));

  try
  (*
      Установка CoInitFlags имеет смысл в файлах проекта (*.dpr, *.lpr)
      и только перед инициализацией ComObj,
      в создаваемых потоках следует вызывать CoInitializeEx();
  *)
  CoInitFlags := COINIT_MULTITHREADED; 
  StartTime := GetTickCount;
  OleCheck(SHGetMalloc( Malloc ));
  try
    OleCheck(SHGetDesktopFolder( desktop ));
      try
        OleCheck(desktop.ParseDisplayName( 0, nil, PWideChar(InitPath), CharsDone,  pidlItself, dwAttributes ));
        try
          OleCheck(desktop.BindToObject(pidlItself, nil, IID_IShellFolder, InitShellDir));
          AppendLog(InitPath);
          ShowFolder( InitShellDir );
        finally
            InitShellDir := nil;         //< перед выходом лучше явно освободить
        end;
      finally
        Malloc.Free(pidlItself);
        desktop := nil;
      end;
    finally
      Malloc := nil;
    end;

  except
          on E:EOleException do
            AppendLog('***** EOleException:  [$'+IntToHex(E.ErrorCode, 8)+'] '+E.Message);
          on E:Exception do
            AppendLog('***** Exception: [$'+IntToHex(GetLastError, 8)+'] '+E.Message);
  end;
  Writeln;
  AppendLog(Utf8ToAnsi('* ГОТОВО * ')); // ух уж этот UTF8 ...
  AppendLog(Format(Utf8ToAnsi('Найдено папок %d  за %f сек. '), [CountFolder, (GetTickCount - StartTime) / 1000]));
  Writeln;
  AppendLog(Utf8ToAnsi('Для завершения нажмите ВВОД ...'));
  readln;
end.

rxt
новенький
 
Сообщения: 15
Зарегистрирован: 03.03.2013 13:54:02

Re: Обход дерева папок с построением списка файлов

Сообщение Ism » 10.07.2013 16:03:08

Это привязка к Винде, нехорошо.

Вот как работать правильно с обходом файлов viewtopic.php?t=9259
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Обход дерева папок с построением списка файлов

Сообщение rxt » 10.07.2013 16:55:00

Ism писал(а):Это привязка к Винде, нехорошо.

Вот как работать правильно с обходом файлов http://freepascal.ru/forum/viewtopic.php?t=9259


  1. Вам следует внимательно перечитать пост ТС, а для holy war о кросплатформенности завести отдельный топик.
  2. Вам следует научиться передавать параметры в процедурах и функциях прежде, чем выкладывать код и судить: где правильно, а где не правильно.
rxt
новенький
 
Сообщения: 15
Зарегистрирован: 03.03.2013 13:54:02

Re: Обход дерева папок с построением списка файлов

Сообщение Ism » 10.07.2013 17:16:53

rxt писал(а):
Ism писал(а):Это привязка к Винде, нехорошо.

Вот как работать правильно с обходом файлов viewtopic.php?t=9259


  1. Вам следует внимательно перечитать пост ТС, а для holy war о кросплатформенности завести отдельный топик.
  2. Вам следует научиться передавать параметры в процедурах и функциях прежде, чем выкладывать код и судить: где правильно, а где не правильно.

О, тролль , чтото их много стало. Наверное тролль хочет чтоб все пали на колени, он же большой.

Читаем верхний пост
(Windows-платформа, если это критично)

Кроссплатформенность всегда в приоритете в FPC, иначе будет никому не нужный код.

Надо купить какой нибудь пестицид , Атитролль подойдет. Давно хотел проверить
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Обход дерева папок с построением списка файлов

Сообщение rxt » 10.07.2013 18:23:01

Ism,
Вместо того, чтобы доказывать истинность своих положений и опровергать аргументацию оппонента, критикуете его личность. Вы жалок. Купите лучше пестицид от говнокода.
rxt
новенький
 
Сообщения: 15
Зарегистрирован: 03.03.2013 13:54:02

Re: Обход дерева папок с построением списка файлов

Сообщение Padre_Mortius » 10.07.2013 21:19:03

rxt, к коду от Ism есть небольшие уточнения, но хотелось бы от вас получить более подробные претензии.

P.S. В вашем коде тоже есть прикольный жучок.
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Обход дерева папок с построением списка файлов

Сообщение alexs » 10.07.2013 21:39:49

rxt
Не надо учить людей плохому. Вместо использования 1-2 стандартных вызовов стандартной библиотеки паскаля вы предлагаете написать подводную лодку и запустить её в космос. Зачем - ActiveX, ShlObj, ComObj?
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Обход дерева папок с построением списка файлов

Сообщение Ism » 10.07.2013 22:28:35

Padre_Mortius писал(а): к коду от Ism есть небольшие уточнения, но хотелось бы от вас получить более подробные претензии.

Если поправите, заброшу в свой пост. Я сделал для себя и отправил рабочий вариант
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Обход дерева папок с построением списка файлов

Сообщение Padre_Mortius » 10.07.2013 23:36:33

Ism, натравите свой алгоритм на папку с hardlink/symlink. Решение этого вопроса лежит тут
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru