C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
FindFirst,FindNext,FindClose, Замучился, бАлин
_NIK_
Отправлено: 03.03.2006, 21:52


Дежурный стрелочник

Группа: Участник
Сообщений: 55



Всем привет!
Зае..ся ваще, что за глюк?
Вот код:
TSearchRec sr;
if (FindFirst(InputDir + "\*.*", faAnyFile, sr) == 0)
{
do
{
if ((sr.Name != ".")&&(sr.Name != ".."))
{
if (sr.Attr == faDirectory)
{
Utf8Encode(InputDir + "\" + sr.Name);
}
if ((sr.Attr != faDirectory)&&(sr.Attr != faVolumeID)&&(sr.Attr != faReadOnly)&&(sr.Attr != faSysFile))
{
TStringList * MyList = new TStringList;
Form1->StatusBar1->Panels->Items[0]->Text = InputDir + "\" + sr.Name;
Form1->StatusBar1->Panels->Items[2]->Text = Form1->StatusBar1->Panels->Items[2]->Text.ToInt() + 1;
Form1->Memo1->Lines->Add(InputDir + "\" + sr.Name);
}
}
} while (FindNext(sr) == 0);
FindClose(sr);
}

Почему этот алгоритм, точнее функции распознают папки у кот. настроен внешний вид за ФАЙЛЫ???
Guest
Отправлено: 03.03.2006, 22:23


Не зарегистрирован







Вместо одиничной косой черты нужен двойной. Напр.

if (FindFirst(InputDir + "\\*.*", faAnyFile, sr) == 0)

Посмотри в helpe: \ (backslash) escape sequences

Note: You must use \\ to represent an ASCII backslash, as used in operating system paths.
_NIK_
Отправлено: 03.03.2006, 22:34


Дежурный стрелочник

Группа: Участник
Сообщений: 55



Косые Черточки ДВОЙНЫЕ, тока почему-то здесь отображаются одинарные!
Guest
Отправлено: 04.03.2006, 01:28


Не зарегистрирован







Ok. Пусть будет, что система виновата... smile.gif

if ((sr.Attr != faDirectory)&&(sr.Attr != faVolumeID)&&(sr.Attr != faReadOnly)&&(sr.Attr != faSysFile))

Нужно, что то типа

if((sr.Attr&faDirectory != faDirectory)....


_NIK_
Отправлено: 04.03.2006, 17:47


Дежурный стрелочник

Группа: Участник
Сообщений: 55



Пробовал...им ваще пофиг какой параметр attr в функции FindFirst и так тож не катит.
Остановился на проверке DirectoryExists(), и рекурсии в блоке:
TStringList * MyList = new TStringList;
Form1->StatusBar1->Panels->Items[0]->Text = InputDir + "\" + sr.Name;
Form1->StatusBar1->Panels->Items[2]->Text = Form1->StatusBar1->Panels->Items[2]->Text.ToInt() + 1;
Form1->Memo1->Lines->Add(InputDir + "\" + sr.Name);
условие убрал поставил else — работает

Отредактировано _NIK_ — 04/03/2006, 17:47
AVC
Отправлено: 06.03.2006, 09:17


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Почему этот алгоритм, точнее функции распознают папки у кот. настроен внешний вид за ФАЙЛЫ???

if (sr.Attr == faDirectory)

Как писал гость
CODE

Attributes can be combined by or-ing their constants or values.

Это условие может не выполняться если каталог не имеет атрибут исключительно faDirectory
Во втором условии то же небходимо использовать сравнение после маскирования.
Grigoriy
Отправлено: 06.03.2006, 15:07


Мастер участка

Группа: Участник
Сообщений: 381



Когда-то я пользуясь этими функциями хотел проверить, как найти самому нужные файлы и каталоги.
Оказывается в файловой системе в каждом каталоге присутствуют каталоги с именами
"."
".."
Пришлось предусмотреть условие, чтобы их пропустить.
Зачем эти каталоги нужны ?

И вообще некоторые каталоги не были ни скрытыми ни системными, но помимо атрибута "faDirectory" имели другой атрибут, который могут иметь файлы, но не означающий, что они скрытые или системные.
То есть, как будто над каталогами этими можно было выполнять чтение так же как и над файлами.
Guest
Отправлено: 06.03.2006, 15:19


Не зарегистрирован







QUOTE

Оказывается в файловой системе в каждом каталоге присутствуют каталоги с именами
"."
".."
Пришлось предусмотреть условие, чтобы их пропустить.
Зачем эти каталоги нужны ?

Для однообразия и упрощения переходов по дереву каталогов
"." — означает текущий каталог и ссылается на себя
".." — означает "шаг назад" и ссылается на родителя
_NIK_
Отправлено: 06.03.2006, 17:18


Дежурный стрелочник

Группа: Участник
Сообщений: 55



QUOTE (Guest @ 06/03/2006, 15:19)
QUOTE

Оказывается в файловой системе в каждом каталоге присутствуют каталоги с именами
"."
".."
Пришлось предусмотреть условие, чтобы их пропустить.
Зачем эти каталоги нужны ?

Для однообразия и упрощения переходов по дереву каталогов
"." — означает текущий каталог и ссылается на себя
".." — означает "шаг назад" и ссылается на родителя

Прикольно у меня получилось, когда я не делал проверку на "." и ".." в рекурсии получался бесконечный цикл biggrin.gif
Doga
Отправлено: 06.03.2006, 17:52


Мастер участка

Группа: Участник
Сообщений: 575



А я не пользуюсь рекурсионными вызовами при просмотре каталогов. Всё делает одна простая функция. Случай был один. Одно чучело на компе которого стояла наша прога, каким то образом умудрилось скопировать несколько каталогов на диске в них же самих, пока ситема позволяла... Так вот, во время сканирования тех каталогов периодически вылетал "StackOverflow" и только на том компе. В коде разбирался долго и ничего не нашёл. А когда выяснилось, все просто попадали состульев biggrin.gif, но меры приняли, о чём собственно я и сказал выше...
Grigoriy
Отправлено: 06.03.2006, 18:09


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (Guest @ 06/03/2006, 15:19)

Для однообразия и упрощения переходов по дереву каталогов
"." — означает текущий каталог и ссылается на себя
".." — означает "шаг назад" и ссылается на родителя

Во спасибо.
Guest
Отправлено: 06.03.2006, 18:24


Не зарегистрирован







QUOTE

А я не пользуюсь рекурсионными вызовами при просмотре каталогов. Всё делает одна простая функция. Случай был один ...

А какая разница рекурсивная или нет если дерево "закольцовано"? Для такого случая можно пользоваться максимальной глубиной вложенности: предел превышен — кольцо. Или анализировать весь пройденный путь, можно поробовать сыграть значениях полей TSearchRec.
_NIK_
Отправлено: 07.03.2006, 01:55


Дежурный стрелочник

Группа: Участник
Сообщений: 55



QUOTE (Doga @ 06/03/2006, 17:52)
А я не пользуюсь рекурсионными вызовами при просмотре каталогов. Всё делает одна простая функция. Случай был один. Одно чучело на компе которого стояла наша прога, каким то образом умудрилось скопировать несколько каталогов на диске в них же самих, пока ситема позволяла... Так вот, во время сканирования тех каталогов периодически вылетал "StackOverflow" и только на том компе. В коде разбирался долго и ничего не нашёл. А когда выяснилось, все просто попадали состульев biggrin.gif, но меры приняли, о чём собственно я и сказал выше...

А какой функцией пользуешься?
_NIK_
Отправлено: 07.03.2006, 01:58


Дежурный стрелочник

Группа: Участник
Сообщений: 55



QUOTE (Guest @ 06/03/2006, 18:24)
QUOTE

А я не пользуюсь рекурсионными вызовами при просмотре каталогов. Всё делает одна простая функция. Случай был один ...

А какая разница рекурсивная или нет если дерево "закольцовано"? Для такого случая можно пользоваться максимальной глубиной вложенности: предел превышен — кольцо. Или анализировать весь пройденный путь, можно поробовать сыграть значениях полей TSearchRec.

Как понять "дерево закольцовано"?
И предел вложенности нельзя использовать — не все файлы найдет!
Doga
Отправлено: 07.03.2006, 08:13


Мастер участка

Группа: Участник
Сообщений: 575



Вот кусок кода. Не гарантирую что в таком виде он будет работать, поскольку я убрал оттуда "всё лишнее" biggrin.gif , но для демонстрации способа сгодится smile.gif .

Вообще то ето тело функции TThread:Execute. В конструктор потока передаются 3 параметра:

1. TStringList *FPathList;
2. Bool FFindBelow;
3. AnsiString FFileMask;
(ну может что ещё...)

В FPathList можно записывать любые пути, вплоть до списка дисков...

CODE

//---------------------------------------------------------------------------
void __fastcall TMonitorThread::Execute()
{
 //---- Place thread code here ----
 int         i,j,k;
 TSearchRec  sr;
 AnsiString  MaskNameString;

 if(FPathList)
 {
   if ( FPathList->Count > 0 )
   {
     //А может пути неверныя?
     for (int i = 0; i < FPathList->Count; i++)
     {
        if (!DirectoryExists(FPathList->Strings[i]))
        {
          FPathList->Delete(i);
          i--;
        }
     }
     
   }
 }
 else //if(!FPathList)
 {
   return;
 }

 //А таперя — поиск всех доступных путёв на всех доступных дисках во всех даступных путях!
 for (i = 0; i < FPathList->Count; i++)
 {
   if (Terminated)
   {
     break;
   }

   //Корректировка пути(дабавлямс '\')
   FPathList->Strings[i] = NormalDir(FPathList->Strings[i]);

   //А ща MaskNameString — енто будет строка с маской имени файла(вааще-то каталога)
   MaskNameString = FPathList->Strings[i] + "*.*";
   //Поиск всех подкаталогов в выбраном каталоге
   for ( j = 0;;j++)  //здесь лучша использовать while, но мне был нужен счётчик j
   {
     if (Terminated)
     {
       break;
     }

     if (!j)
     {
       if (FindFirst(MaskNameString, faAnyFile, sr))
       {
         FindClose(sr);
         break;
       }
     }
     else
     {
       if (FindNext(sr))
       {
         FindClose(sr);
         break;
       }
     }

     //Добавлямс новый путь к списку (ежели енто каталог)
     if(sr.Attr&faDirectory)
     {
       //Ежежели енто, канюшно, разрешено
       if(FFindBelow == true)
       {
         if((sr.Name != ".") && (sr.Name != ".."))
         {
           k = FPathList->Add(FPathList->Strings[i] + sr.Name);
           FPathList->Strings[k] = FPathList->Strings[k].Unique();
         }
       }
     }
     //А коли файла папаласи — устроим ей тут жа праверку на вшивость
     else if(!(sr.Attr&FBadAttributes))
     {
       //Таперя проверим, а не совпадает ли найденный файл с
       //нужной маской поиска — FFileMask
       if (MatchesMask(sr.Name, FFileMask))
       {
         //собственно здесь производятся необходимые действия с найденным файлом...
       }
     }

   }
 }
 

 if(FPathList)
 {
   delete FPathList;
   FPathList = NULL;
 }
}
//---------------------------------------------------------------------------

Вернуться в Вопросы программирования в C++Builder