Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Парсер путей файлов [D5, WinXP]


dimaxx ©   (2004-11-13 13:28:00) 

Есть список путей типа:

aaa\bbb\file.dat

Нужно распарсить весь список для выделения файлов и папок корневой директории и т.д. вглубь дерева. Также делает TotalCommander при входе в архив (ему как раз передается такой список).

Если кто видел ссылу на подобное или есть пример/сырец - киньте, плз.


dimaxx   (2004-11-17 22:49:00) [1]

Спасибо большое! Правда я сам уже написал, но работает громоздко. Но главное работает. Попробую еще этот вариант.


Defunct   (2004-11-17 00:07:00) [2]

dimaxx, то что вам нужно, а именно дерево, отображается методом DrawTree [9].
Строится дерево в теле метода Load

Пример использования объекта TFolderControl можно посмотреть в процедуре CheckFolder.


Defunct   (2004-11-16 23:56:00) [3]

Я с вами поделюсь рабочим модулем из одного из моих проектов. Модуль был написан под DOS на TP7, так что вы можете его улучшить.

Unit Folders;

Interface

Type
    TDirDOSName = String[12];

    PChainRec = ^TChainRec;
    TChainRec = Record
      Folder : String;     { TDirDOSName;}
      Exists : Boolean;
      N      : PChainRec;
    End;

    TFolderControl = Object
    Private
      Root      : PChainRec;
      Tail      : PChainRec;
      BackupDir : String;

      Procedure ClearFolderRec(Folder:PChainRec);
      Procedure Clear;
      Procedure DrawTree; {Debug only }
      Function  DirExists(P:PChainRec):Boolean;
      Function  ExpandFolderName(P:PChainRec):String;
    Public
      Correct : Boolean;
      Exists  : Boolean;
      Error   : Integer;

      Function    Name:String;
      Function    ExpandFilePath(FileName:String):String;
      Procedure   Load(Folder:String);
      Procedure   CreateFolder;
      Procedure   EnterIt;
      Procedure   LeaveIt;

      Constructor Init;
      Destructor  Done;
    End;

Procedure CheckFolder(Folder:String);
Function  FileExists(FileName:String):Boolean;
Function  ExtractFileName(FileName:String):String;

Var
   CritError : Integer;

Implementation

Const DOSNameSymbols = ['A'..'Z','.','0'..'9','a'..'z','~'];

{****************************}
{****** Folder Control ******}
{****************************}

Constructor TFolderControl.Init;
Begin
 Root    := Nil;
 Tail    := Nil;
 Correct := False;
 Exists  := False;
 Error   := 0;
 BackupDir := '';
End;

Procedure TfolderControl.ClearFolderRec;
Begin
 If Assigned(Folder) Then
 Begin
   Folder^.Folder := '';
   Folder^.Exists := False;
   Folder^.N := Nil;
 End;
End;

Procedure TFolderControl.Clear;
Var P,P2:PChainRec;
Begin
 P := Root;
 While P<>Nil Do
 Begin
   P2 := P;
   P := P^.N;
   Dispose(P2);
 End;
 Root := Nil;
End;

Procedure TFolderControl.DrawTree;
Var P:PChainRec;
Begin
 P := Root;
 While P<>Nil Do
 Begin
   WriteLn(P^.Folder);
   P := P^.N;
 End;
End;

Function TFolderControl.Name;
Begin
 Name := ExpandFolderName(Tail);
End;

Function TFolderControl.ExpandFilePath;
Var Dir:String;
Begin
 Dir := Name;
 If Dir[Length(Dir)] <> '\' Then
    ExpandFilePath := Dir + '\' + FileName Else
    ExpandFilePath := Dir + FileName;

End;

Function TFolderControl.ExpandFolderName;
Var PL,Last:PChainRec;
   FName : String;
Begin
 PL := Root;
 FName := '';
 If PL<>Nil Then
 Repeat
   If PL=Root Then FName := FName + PL^.Folder Else
   Begin
     If FName[Length(FName)]<>'\' Then FName := FName + '\';
     FName := FName + PL^.Folder;
   End;
   Last := PL;
   PL := PL^.N;

 Until (PL = Nil) Or (Last = P);

 ExpandFolderName := FName;

End;

Function TFolderControl.DirExists;
Var Backup : String;
Begin
{$I-}
 GetDir(0, Backup);
 ChDir(ExpandFolderName(P));

 DirExists := IOResult=0;
 ChDir(Backup);
{$I+}
End;

Procedure TFolderControl.Load(Folder:String);
Var Current   : Integer;
   SubFolder : String;
   P,PL      : PChainRec;
Begin
 Current := 1;
 Error   := 0;
 PL      := Nil;
 SubFolder := '';
 Clear;
 While Current<=Length(Folder) Do
 Begin
   Case Folder[Current] Of
     ':'    :
     Begin { Disk }
       If (Root=Nil) And (Length(SubFolder)=1) Then
       Begin
         New(P);
         ClearFolderRec(P);
         P^.Folder := SubFolder + ':\';
         Root := P;
         PL   := P;
         P^.Exists := DirExists(P);
       End Else
       Begin
         Inc(Error);
       End;
       SubFolder := '';
     End;
     '\'    :
     Begin
       If (PL<>Nil) And
          (Length(SubFolder)>0) And (Length(SubFolder)<=12) Then
       Begin
         New(P);
         ClearFolderRec(P);
         P^.Folder := SubFolder;
         PL^.N := P;
         PL    := P;
         P^.Exists := DirExists(P);
       End Else
       If (Length(SubFolder)=0) And (PL=Root) Then
       Begin
         { Here is no error }
       End Else
       Begin
         Inc(Error);
       End;
       SubFolder := '';
     End;

     Else If Folder[Current] in DOSNameSymbols Then
     Begin
       SubFolder := SubFolder + Folder[Current];
     End
   End;
   Inc(Current);
 End;

 Tail := P;
 Exists := Tail^.Exists;
{  DrawTree;  {Debug}
End;

Procedure TFolderControl.CreateFolder;
Var P:PChainRec;
Begin
 P := Root;
 While P<>Nil Do
 Begin
   If (P=Root) And (Not DirExists(P)) Then
   Begin
     P := Nil;
     Inc(Error);
   End Else
   If (P<>Root) And (Not DirExists(P)) Then
   Begin
   {$I-}
     MkDir(ExpandFolderName(P));
     If IOResult<>0 Then Inc(Error);
   {$I+}
   End;

   P := P^.N;
 End;
End;

Procedure TFolderControl.EnterIt;
Begin
 CreateFolder;
{$I-}
 GetDir(0, BackupDir);
 ChDir(ExpandFolderName(Tail));
 If IOResult<>0 Then Inc(Error);
{$I+}
End;

Procedure TFolderControl.LeaveIt;
Begin
{$I-}
 ChDir(BackupDir);
 If IOResult<>0 Then Inc(Error);
{$I+}
End;

Destructor TFolderControl.Done;
Begin
 Clear;
End;
{****************************}

Function FileExists(FileName:String):Boolean;
Var F:File;
Begin
{$i-}
 Assign(F, FileName);
 Reset(F);
 Close(F);
{$i+}
 FileExists := IOResult=0;
End;

Function ExtractFileName(FileName:String):String;
Var S        : String;
   Pos,Dots : Integer;
   Done     : Boolean;
Begin
 S:= ''; Dots := 0;
 Pos := Length(FileName);
 Done := False;

 While (Length(S)<12) And (Pos<>0) And (Not Done) do
 Begin
   If FileName[Pos] in DOSNameSymbols Then
   Begin
     If FileName[Pos] = '.' Then Inc(Dots);
     If Dots<2 Then S:= FileName[Pos] + S
               Else Done := True;
   End Else
   Begin
     Done := True;
   End;
   Dec(Pos);
 End;
 ExtractFileName := S;
End;

Procedure CheckFolder(Folder:String);
Var FC : TFolderControl;
Begin
 FC.Init;
 FC.Load(Folder);
 WriteLn('Selected folder => ',FC.Name,'.....');
 If Not FC.Exists Then
 Begin
   FC.CreateFolder;
   WriteLn('not exists, making the folder ',FC.Name);
 End;

 If FC.Error>0 Then
 Begin
   WriteLn('Errors detected during a folder creation, error count: ',FC.Error);
   CritError := FC.Error;
 End;

 FC.Done;
End;

End.


dimaxx   (2004-11-16 23:48:00) [4]

Мля, дядьки! Я вроде прально выражовывался в первом посте! Мне нужно, например, из списка файлов (которые получены из архива) типа:

aaa\bbb\file1.dat
aaa\bbb\file2.dat
aaa\bbb\file3.dat
aaa\bbb\file4.dat
ссс\ddd\file.bin
ссс\file.001
readme.txt


Нужно выдать в ListView сначала:

aaa
ccc
readme.txt


где aaaи ссс- папки, а readme.txt- файл. Потом пользователь может войти в папку ссс и увидеть следующее:

ddd
file.001


Причем тут сортировка? У меня список состоит из более чем 3000 файлов. Я спрашиваю алгоритм, по которому я смогу выдрать все файлы и папки корневого уровня, потом первого и т.д.


[lamer]Barmaglot   (2004-11-16 09:34:00) [5]

то Dimaxx ©   (16.11.04 00:03) [6]

Мбр...Включить в Листвиев сортировку? И сортировать так как тебе надо?


Dimaxx   (2004-11-16 00:03:00) [6]

Оттуда же. Я писал, что есть список файлов (например, в TSrtingList) с относительными путями, которые получены из архива, т.е. нет таких файлов на диске. Поэтому FindNext/FindFirst не катит. Но мне нужно вывести их как в файловой панели TotalCommander'а и чтоб пользователь смог "гулять по архиву": входить в папки, помечать файлы для удаления/извлечения. То есть сформировать дерево папок в TListView. Для TTreeView у меня код есть, а мне нужен для ListView.


Poirot   (2004-11-14 23:46:00) [7]

Тебе что надо сделать-то:) моя как то смутно полагает что мб FindNext FindFirst поможет:)
Как говорится сформулируй вопрос немного поточнее:)
Как это делай тотал командер в архивах - дык он просто выводит все папки и файлы по дпнному пути. От читает из архива, а тебе откуд надо читаь!?


dimaxx   (2004-11-14 22:23:00) [8]

Да нет, братцы, вы не поняли. Мне нужно из этой мешанины вытаскивать имена папок и файлов определенного уровня. Сначала все корневые, потом список файлов и папок какй-то выбранной пользователем папки. Так как вы действуетет в TotalCommander при "гулянии" по архиву.

2 Palladin: Без тебя знаю! :-)

2 Sam Stone: Про рекурсию в курсе, но как это сделать. Я прошу как раз совета или пример как это сделать. Распарсить на составляющие я могу, а как выбрать нужное?


begin...end   (2004-11-13 13:49:00) [9]

dimaxx ©   (13.11.04 13:28)

Разумеется, можно [1]. Но есть и ещё вариант.

Задача очень похожа на вот эту:

http://www.delphimaster.ru/cgi-bin/forum.pl?id=1100277025&n=0(посты [1] и [8])

с той лишь разницей, что в Вашем случае разделителем является символ "\".


Sam Stone   (2004-11-13 13:47:00) [10]

рекурсией обходи папки, собирай полные имена файлов, а после ищи в имени символ "\". Вот и все. Можно еще использовать ExtractFileName, ExtractFilePath (кажется, так пишутся).


Palladin   (2004-11-13 13:41:00) [11]

Pos, Copy + F1


Наверх

Титульная страница Поиск, карта сайта Написать письмо