Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.01.2013, 02:31   #1
Raf-9600
Пользователь
 
Регистрация: 10.07.2012
Сообщений: 34
Счастье Два вопроса по рекурсивному поиску файлов

Откопал на просторах интернета замечательную процедуру на поиск файлов в подпапках, но возникло пару вопросов в которых я не в силах разобраться:
1. Как можно прикрутить вместо Memo вывод данных в какой-то не визуальный объект, к примеру StringList?
2. Допустим мне нужно чтобы в самом конце создаваемого процедурой списка, один раз производилось какое-то действие, к примеру memo1.Lines.Add('End'); когда я эту строчку записываю после FindClose(sRec); то слово End повторяется столько раз, сколько отработала процедура. Можно ли это как-то обойти, чтобы memo1.Lines.Add('End') отработал только один раз?

Код:
procedure TForm1.GetAllFiles(Path: string; Lb: TMemo);
var
  sRec: TSearchRec;
  isFound: boolean;

begin
   Path := IncludeTrailingBackslash(Path);
   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) // Перезапускаем процедуру передавая ей вложенную папку
         else
         begin
            Lb.Lines.Add(Path + sRec.Name);

         end;
      end;
      Application.ProcessMessages;
      isFound := FindNext(sRec) = 0;
   end;
   FindClose(sRec);
end;
Raf-9600 вне форума Ответить с цитированием
Старый 06.01.2013, 12:46   #2
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Код:
procedure TForm1.GetAllFiles(Path: string; SL: TStrings);
var
  sRec: TSearchRec;
  isFound: boolean;

begin
   Path := IncludeTrailingBackslash(Path);
   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, SL) // Перезапускаем процедуру передавая ей вложенную папку
         else
         begin
            SL.Add(Path + sRec.Name);

         end;
      end;
      Application.ProcessMessages;
      isFound := FindNext(sRec) = 0;
   end;
   FindClose(sRec);
end;

procedure TForm1.MyFiles(Path: string; SL: TStrings)
begin
  MyGetAllFiles(Path, SL);
  SL.Add('End');
end;
Вызывать, например, так:
Код:
MyFiles('C:\', Memo1.Lines);
или
SL1 := TStringList.Create();
MyFiles('C:\', SL1);
Код не проверял, тут написал, ибо всё тривиально.
phomm вне форума Ответить с цитированием
Старый 06.01.2013, 13:15   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

phomm, +1

на форуме тема поиска файлов рассматривалась огромное множество раз. (поиск по FindFirst, посмотрите, например)
Позволю себе привести ссылочку на свой пост (хотя, по сути он такой же мой, как и всех других! )
Serge_Bliznykov вне форума Ответить с цитированием
Старый 06.01.2013, 17:21   #4
Raf-9600
Пользователь
 
Регистрация: 10.07.2012
Сообщений: 34
По умолчанию

Цитата:
Сообщение от phomm Посмотреть сообщение
Код не проверял, тут написал, ибо всё тривиально.
Дык у меня возникает почти та же ошибка что и при использовании StringList вместо Strings, компилятор подчеркивает красным
Код:
SL.Add(Path + sRec.Name)
и пишет ошибку:


А при выводе данных в Memo всё работает отлично. Собсно поэтому и создавал тему.

Последний раз редактировалось Raf-9600; 06.01.2013 в 17:25.
Raf-9600 вне форума Ответить с цитированием
Старый 06.01.2013, 17:25   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Вы наверняка забыли создать объект, который передаёте в качестве параметра SL

Цитата:
Сообщение от phomm
Код:
SL1 := TStringList.Create;
MyFiles('C:\', SL1);
Serge_Bliznykov вне форума Ответить с цитированием
Старый 06.01.2013, 17:35   #6
Raf-9600
Пользователь
 
Регистрация: 10.07.2012
Сообщений: 34
По умолчанию

Serge_Bliznykov, Вы правы
Благодарю за подсказку.
Raf-9600 вне форума Ответить с цитированием
Старый 06.01.2013, 17:45   #7
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Отлично. Поздравляю.

И не забудьте, как правило, всё, что Вы в программе создали руками, нужно в своей же программе и освободить - вызывать метод SL1.Free или воспользоваться процедурой FreeAndNil( SL1 ) (это почти одно и то же. Процедура дополнительно обнуляет указатель на объект, что более безопасно в плане попыток использования указателя в программе в дальнейшем)
Serge_Bliznykov вне форума Ответить с цитированием
Старый 06.01.2013, 21:01   #8
Raf-9600
Пользователь
 
Регистрация: 10.07.2012
Сообщений: 34
По умолчанию

У меня возникла ещё одна трудность: почему-то не получается сделать так, чтобы записываемая строка была уже отформатированной:
Код:
procedure TForm1.GetAllFiles(Path: string; SL: TStringList);
var
  sRec: TSearchRec;
  isFound: boolean;

begin
   Path := IncludeTrailingBackslash(Path);
   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, SL) // Перезапускаем процедуру передавая ей вложенную папку
         else
         begin
             SL.Add(StringReplace(Path + sRec.Name, FirstPath,'',[]));
         end;
      end;
      Application.ProcessMessages;
      isFound := FindNext(sRec) = 0;
   end;
   FindClose(sRec);
end;
Где FirstPath это глобальная строковая переменная с изначальным путем к папке. В общем как я понял, в процедуре нельзя читать глобальные переменные. Собсно можно ли это обойти, чтобы в StringList записывались сразу отформатированные строки? Или я снова упустил какую-то мелочь?

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
И не забудьте, как правило, всё, что Вы в программе создали руками, нужно в своей же программе и освободить
Дык вроде ж все переменные созданные в процедуре, живут только во время действия этой процедуры, а значит в данном случае нет смысла их вручную освобождать. Разве я ошибаюсь?

Последний раз редактировалось Raf-9600; 06.01.2013 в 22:51.
Raf-9600 вне форума Ответить с цитированием
Старый 07.01.2013, 01:38   #9
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Дык вроде ж все переменные созданные в процедуре, живут только во время действия этой процедуры, а значит в данном случае нет смысла их вручную освобождать. Разве я ошибаюсь?
старшие товарищи меня поправят, если я не прав, но, на мой взгляд, Вы ошибаетесь.
допустим, Вы написали var SL1 : TStringList;
эта переменная (ссылка на объект, == pointer) занимает в Win 32 4 байта.
Вы выделяете память под объект, грузите туда кучу строк, потом выходите из процедуры, не вызвав декструктор. Сколько памяти будет освобождено? Верно - 4 байта. А та туева куча строк так и будет висеть в памяти, отмеченная, как занятая.
Разумеется, когда Ваша программа закроется, то вся занятая программой память будет отдана системе, но каждый вызов вашей процедуры в программе будет приводит к тому, что памяти будет становится всё меньше, меньше, меньше.. это называется "memory leaks"

Цитата:
чтобы записываемая строка была уже отформатированной:
простите, у меня с телепатией напряги... что значит "отформатированной" ?
Serge_Bliznykov вне форума Ответить с цитированием
Старый 07.01.2013, 01:57   #10
Raf-9600
Пользователь
 
Регистрация: 10.07.2012
Сообщений: 34
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
Разумеется, когда Ваша программа закроется, то вся занятая программой память будет отдана системе, но каждый вызов вашей процедуры в программе будет приводит к тому, что памяти будет становится всё меньше, меньше, меньше.. это называется "memory leaks"
Хм... Перед каждым началом обработки я вызываю для него .Clear; - судя по сведениям из диспетчера задач, это помогает освободиться от мусора.

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
простите, у меня с телепатией напряги... что значит "отформатированной" ?
Отредактированная. Т.е. чтобы кусок от неё удалялся. Ну допустим есть изначальная папка "D:\Torrent Downloads\Книги\Delphi" этот путь передается в процедуру поиска файлов, которая создаёт список файлов в StringList. В StringList записываются полные пути к файлам, а необходимо чтобы записывались без этой строчки "D:\Torrent Downloads\Книги\", т.е. чтобы в результате в StringList было не:
Цитата:
D:\Torrent Downloads\Книги\Delphi\Библия, издание 1.doc
D:\Torrent Downloads\Книги\Delphi\Библия, издание 2.doc
D:\Torrent Downloads\Книги\Delphi\Библия, издание 3.doc
D:\Torrent Downloads\Книги\Delphi\Примеры\Drag and Drop.txt
А так:
Цитата:
Delphi\Библия, издание 1.doc
Delphi\Библия, издание 2.doc
Delphi\Библия, издание 3.doc
Delphi\Примеры\Drag and Drop.txt
Я конечно нашел альтернативный способ выкрутиться, и обрабатываю каждую строку из StringList после того как процедура поиска файлов завершилась, но мне просто любопытно, можно ли такое сделать сразу в той процедуре?

Последний раз редактировалось Raf-9600; 07.01.2013 в 02:11.
Raf-9600 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Два простых вопроса skvair C++ Builder 4 31.01.2012 22:28
Два небольших вопроса :) f4rr3l Паскаль, Turbo Pascal, PascalABC.NET 5 10.01.2009 12:44
Два тупых вопроса. proglamer Общие вопросы Delphi 2 10.04.2008 07:12
Два вопроса Никки Общие вопросы Delphi 2 19.01.2008 21:39
Два простых вопроса Relrin Общие вопросы Delphi 3 28.12.2007 16:00