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

 
FindFirst, путь к файлу
Лена
Отправлено: 11.11.2006, 14:50


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

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



Написала код, который ищет самый новый файл по дате. Подскажите, как его подправить, чтобы в переменную S записывался полный путь к этому файлу. Например, C:\Foto\1.gif где 1.gif это самый новый по дате создания файл, на диске С.
Что-то кручу — кручу, а получается ерунда. smile.gif

CODE

void LookInDir(AnsiString DirName,   TDateTime D)
{

 TSearchRec sr;
 AnsiString S;
 for(int r=FindFirst(DirName+"\\*.*",faDirectory,sr);!r;r=FindNext(sr))
   if((sr.Attr&faDirectory) && (sr.Name!="." && sr.Name!=".."))
     LookInDir(DirName+"\\"+sr.Name,  0);
 FindClose(sr);
 for(int r=FindFirst(DirName+"\\*.*",faDirectory,sr);!r;r=FindNext(sr))
       if (FileDateToDateTime(sr.Time) > D)
       {
        D = FileDateToDateTime(sr.Time);
        S = sr.Name;
       }
     FindClose(sr);

 Form1->ListBox1->Items->Add(S);//как тут сформировать путь к файлу?

}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  LookInDir("C:\\Foto", 0);
}

__Cheat3r
Отправлено: 11.11.2006, 15:33


Станционный диспетчер

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



или я не понял, или
CODE
Form1->ListBox1->Items->Add(DirName+"\\"+S);//как тут сформировать путь к файлу?
Лена
Отправлено: 12.11.2006, 11:01


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

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



Мне нужно чтобы в ListBox1 попадала только первая запись (см. рисунок). При этом код должен всегда находить самый новый файл на диске, не взирая на то, где он лежит в корне или в других папках.



Присоединить изображение

Присоединить изображение

beginner
Отправлено: 12.11.2006, 16:38


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

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



Для того, чтоб попала только одна запись,
нужно передавать время, как ссылку на переменной, и
S тоже передавать как AnsiString &, т.е. ф-ия должна бы иметь
вид

void LookInDir(AnsiString DirName, TDateTime &D, AnsiString &S)

И из ф-ии нужно удалить

ListBox1->Items->Add(S);
CODE
void TForm1::LookInDir(AnsiString DirName, TDateTime &D, AnsiString &S)
{
TSearchRec sr;
for(int r=FindFirst(DirName+"\\*.*",faDirectory,sr);!r;r=FindNext(sr))
{
if((sr.Name == ".")||(sr.Name==".."))continue;
if(sr.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
LookInDir(DirName + "\\" + sr.Name, D, S);
else if(FileDateToDateTime(sr.Time) > D)
{
D = FileDateToDateTime(sr.Time);
S = DirName + "\\" + sr.Name;
}
}
FindClose(sr);
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDateTime dt = 0;
AnsiString S = "";
LookInDir("C:\\Foto", dt, S);
if(S!="")
ListBox1->Items->Add(S);
}


Отредактировано beginner — 12.11.2006, 17:56
Лена
Отправлено: 13.11.2006, 11:10


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

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



Cпасибо!
Передача по ссылке, все сделала как надо. smile.gif

P.S.
Скажите как подправить цикл, на случай если папок очень много?
Чтобы приложение отвечала на запросы добавила в конце цикла: Application->ProcessMessages(); Однако если папок много (например корень диска С), то почем то находится не самый новый файл.

Отредактировано Лена — 13.11.2006, 16:49
Лена
Отправлено: 13.11.2006, 17:02


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

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



Кажется нашла. Все время находиться стандартный файл от Windows: C:\Documents and Settings\All Users\Documents\Ico\Icons2\Zamok256.ICO и у него почему-то дата изменения 2015 год. Не понятно. ohmy.gif

P.S. Посмотрела в этой папке у всех стоит 2015 год. wizard.gif
(Windows XP SP2 Media Edition)
На диске D нормально ищет.

Отредактировано Лена — 13.11.2006, 17:06

Присоединить изображение

Присоединить изображение

Konstantine
Отправлено: 13.11.2006, 17:39


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

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



ИМХО в данном случае стоило бы сделать переменную D статической. именно это и ест ьобласть применения статики — в рекурсивных функциях
Лена
Отправлено: 13.11.2006, 17:59


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

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



Cделала D статической.

Еще вопрос. Какое правильное условие добавить в цикл, чтобы в ListBox1 мог попасть только файл с раширением "*.jpg", "*.jpeg", "*.gif" а остальные просто отсекались?
Лена
Отправлено: 13.11.2006, 18:26


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

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



Вот так придумала. Надежно?
CODE

void LookInDir(AnsiString DirName, TDateTime &D, AnsiString &S)
{
TSearchRec sr;
AnsiString EXE;
for(int r=FindFirst(DirName+"\\*.*",faDirectory,sr);!r;r=FindNext(sr))
{

  if((sr.Name == ".")||(sr.Name==".."))continue;
  if(sr.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
    LookInDir(DirName + "\\" + sr.Name, D, S);
  else if(FileDateToDateTime(sr.Time) > D)
  {
    D = FileDateToDateTime(sr.Time);
    EXE = sr.Name;
    int pos = EXE .Pos(".");
    EXE = Trim(EXE.SubString(pos+1,EXE.Length()));
    if (EXE == "jpeg" || EXE == "jpg" || EXE == "gif")
    {
     S = DirName + "\\" + sr.Name;
    }



  }
  Application->ProcessMessages();
}
FindClose(sr);
}

Shagg
Отправлено: 13.11.2006, 19:08


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

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



Надежно, только расширение лучше получать функцией ExtractFileExt, т.к. для имен типа "111.tar.gz" или "my.picture.jpg" поиск по точке даст неверное расширение. Либо искать самую правую точку — тож вариант.
beginner
Отправлено: 13.11.2006, 19:39


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

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



D = ...
нужно бы перенести в блок перед
S = ...
Лена
Отправлено: 14.11.2006, 11:29


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

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



Окончательный вариант, значит получается такой:
CODE

void LookInDir(AnsiString DirName, TDateTime &D, AnsiString &S)
{
TSearchRec sr;
AnsiString EXE;
for(int r=FindFirst(DirName+"\\*.*",faDirectory,sr);!r;r=FindNext(sr))
{

  if((sr.Name == ".")||(sr.Name==".."))continue;
  if(sr.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
    LookInDir(DirName + "\\" + sr.Name, D, S);
  else if(FileDateToDateTime(sr.Time) > D)
  {

    EXE = ExtractFileExt(sr.Name);

    if (EXE == ".jpeg" || EXE == ".jpg" || EXE == ".gif" || EXE == ".JPG"
               || EXE == ".JEPG" || EXE == ".GIF")
    {
     D = FileDateToDateTime(sr.Time);
     S = DirName + "\\" + sr.Name;
    }


  }
  Application->ProcessMessages();
}
FindClose(sr);
}



Вызов:
CODE

static TDateTime dt = 0;
               AnsiString S = "";
               //PathFolder — нужный путь
               LookInDir(PathFolder, dt, S);
               if(S!="")
                {
                  Form1->AdvPicture1->Picture->LoadFromFile(S);
                }


Когда папок много, хочу добавить прогресс бар, чтобы пользователь видел процесс поиска. Как правильно задать границы этого прогресс бара?
olegenty
Отправлено: 14.11.2006, 11:48


Ветеран

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



никак, пока всё дерево не отсканируешь. так что просто можешь показывать текущий каталог в какой-нить Label + количество отсканеных.
Лена
Отправлено: 14.11.2006, 12:03


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

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



Понятно.

Подумаю, может еще такой вариант: какой-нибудь прогресс бар, который бы бегал как при загрузке Windows.

P.S.
Индификатор static пришлось убрать. Если вторично подсоединить флеш носитель во время выполнения программы, то картинка уже не находиться.
Doga
Отправлено: 14.11.2006, 12:20


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

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



Привет! smile.gif

QUOTE

может еще такой вариант: какой-нибудь прогресс бар, который бы бегал как при загрузке Windows

Однозначно — лучше не придумаешь!

А вообще, не так давно, я выкладывал пример НЕрекурсивной функции поиска файлов, может быть — пригодится... rolleyes.gif

http://www.rxlib.ru/forums/index.php?act=S...ad3cfd1b665795b

Самый последний пост...

Отредактировано Doga — 14.11.2006, 12:22
history
Отправлено: 28.11.2009, 10:04


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







Если поиск начинается с корневого каталого, то судя по твоему коду ты способна узнать размер файла которого ты в данный момент анализируешь. Таким образом зная занятое место на диске + сумму размеров уже проверенных файлов, ты способна будешь расчитать процент хода работы программы.

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