Newsgroup: it.comp.programmare.win32
Titolo: cercare file su disco con c++

Salve a tutti!
qualcuno sa dirmi come posso muovermi se devo scrivere una funzione
che cerchi un file su disco in un sistema windows? In particolare con
le funzioni FindFirstFile e FindNextFile posso trovare un file nella
directory corrente, ma come faccio a fare uno scan su tutto l'albero
c:\ ?
spero di essere stato chiaro
grazie
wok

 wok

 }
int Scan(LPTSTR dir,..../*altri parametri*/)
{
  _tcscat(dir,_T("\\*.*"));
  WIN32_FIND_DATA findData;
  HANDLE hFind=FindFirstFile(dir,&findData);
  if(hFind != INVALID_HANDLE_VALUE)
  {
      BOOL ok = TRUE;
      while(ok)
      {
         if((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)  /*
è una directory*/
         {
            Scan(findData.cFileName,....);
         }
         else  /* è un file*/
         {
            AltreOperazioni( findData.cFileName);
         }
         ok=FindNextFile(hFile,&findData);
      }
      FindClose(hFind);
  }
  return 0;
}
C'era qualche piccolo baco nella tua funzione (e magari adesso ce n'è anche
qualcuno mio):
- Bisogna controllare che l'handle ritornato da FindFirstFile non sia
INVALID_HANDLE_VALUE, cioè che la prima ricerca non sia già fallita.
- Bisogna controllare che dwFileAttributes abbia il bit
FILE_ATTRIBUTE_DIRECTORY impostato e non che sia uguale a
FILE_ATTRIBUTE_DIRECTORY, poiché potrebbe avere altri bit impostati e
l'uguaglianza non sussisterebbe più.
- La chiamata FindNextFile deve essere messa in fondo al ciclo while perché
altrimenti i dati di findData restituiti da FindFirstFile verranno
sovrascritti perdendo i dati relativi al primo file trovato; in più, quando
la variabile ok diventerà FALSE (i dati di findData non saranno validi o,
peggio, saranno gli stessi dell'iterazione precedente), il blocco di
elaborazione sarà eseguito ugualmente.
- L'handle hFind dovrebbe essere rilasciato con FindClose.
Ciao
Stefano

 Stefano
ciao.

 ha scritto nel messaggio
news:a7cpl9$57ia$1...@stargate1.inet.it...
[mega cut]
a guarare bene ne avevo scritte parecchie di c*****e
sorry :-(

Innanzitutto grazie per l'aiuto. Purtroppo però ho scritto questa
funzione che non ne vuole sapere di funzionare...sapreste dirmi il
perchè?
In questo caso il codice prevede che quando si trova il file "p.pdb"
mi scrive "file trovato". Come path alla prima chiamata passo c:\*.* o
qualunque altra directory sequita da *.*   Il risultato è che mi manda
a schermo la stringa "Invalid file handle....." alla riga
10....Perchè?
int Scan_Tree(LPTSTR path) {
	BOOL fFinished = FALSE;
	HANDLE hFind;
	WIN32_FIND_DATA FindFileData;
// ad ogni chiamata ricorsiva inizializza l'handle
	hFind = FindFirstFile(path, &FindFileData); 
	if (hFind == INVALID_HANDLE_VALUE) {
		  printf ("Invalid File Handle. Get Last Error reports %d\n",
GetLastError ());
		  return(0);
	  } 
// inizia il ciclo di scan della directory
	while (!fFinished) {
// se il file corrente è un repertorio chiama ricorsivamente la
funzione
	  if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
		  Scan_Tree(FindFileData.cFileName);
	  }
 
// se il file corrente è il file che sto cercando fai qualcosa 		
	  if (strcmp(FindFileData.cFileName, "p.pdb") == 0) {
		  printf("file trovato p.pdb\n");			
	  }
// altrimenti passa al file successivo a meno che non sei arrivato
alla fine
 
	  if (!FindNextFile(hFind, &FindFileData)) {
 		  if (GetLastError() == ERROR_NO_MORE_FILES) 
		  { 
			  fFinished = TRUE; 
		  } 
      }
	}
	FindClose(hFind);
	return(0);
}

che cerchi un file su disco in un sistema windows? 
Non serve scriverla, c'e' gia'.
SearchTreeForFile.
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

Ho modificato la tua funzione come segue:
// prototipo
int Scan_Tree(LPTSTR);
int main(int argc, char* argv[])
{
// La funzione viene chiamata passando solo il percorso
 Scan_Tree(_T("c:\\PercorsoIniziale"));
 return 0;
}
int Scan_Tree(LPTSTR path)
{
 BOOL fFinished = FALSE;
 HANDLE hFind;
 WIN32_FIND_DATA FindFileData;
 LPTSTR tsz1(NULL);
// Stringa temporanea per accodare *.* e preservare il path
 tsz1 = new TCHAR[_tcslen(path) + 5];
 _tcscpy(tsz1,path);
 _tcscat(tsz1,_T("\\*.*"));
 hFind = FindFirstFile(tsz1, &FindFileData);
 delete []tsz1;
 if(hFind == INVALID_HANDLE_VALUE)
 {
  printf ("Invalid File Handle. Get Last Error reports %d\n",
  GetLastError ());
  return(0);
 }
 while(!fFinished)
 {
// Mi raccomando di testare il bit e non l'uguaglianza
  if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
  {
// Qui bisogna ricordarsi di scartare le directory "." e ".."
   if((_tcscmp(FindFileData.cFileName,_T(".")) != 0) &&
    (_tcscmp(FindFileData.cFileName,_T("..")) != 0))
   {
// Una seconda stringa temporanea viene utilizzata
// per costrurire il parametro per la chiamata ricorsiva
// che deve essere composto dal path originale più la
// directory che andremo a scandire
    LPTSTR tsz2(NULL);
    tsz2 = new TCHAR[_tcslen(path) + _tcslen(FindFileData.cFileName) + 2];
    _tcscpy(tsz2,path);
    _tcscat(tsz2,_T("\\"));
    _tcscat(tsz2,FindFileData.cFileName);
    Scan_Tree(tsz2);
    delete []tsz2;
   }
  }
  if (_tcscmp(FindFileData.cFileName, _T("p.pdb")) == 0)
  {
   _tprintf("File trovato in %s\n\n",path);
  }
  if(!FindNextFile(hFind, &FindFileData))
  {
   if(GetLastError() == ERROR_NO_MORE_FILES)
   {
    fFinished = TRUE;
   }
  }
 }
 FindClose(hFind);
 return(0);
}
Questa volta l'ho provata e funziona.
Ciao.
Stefano.

 perchè?
[cut]
dai anche un occhiata alla risposta di andrea + avanti;sinceramente
quell'api non la conoscevo.
ciao.

...


dir che scandisce č 32,
32 e' la profondita' massima di scansione, non il numero
massimo di directory che scandisce:
Dovrebbe funzionare:
// C++ Builder 5.0
#include <windows.h>
#include <stdio.h>
void RecSearchFiles(const char *folder)
{
     BOOL c;
     HANDLE h;
     WIN32_FIND_DATA ffd;
     char CurDir[300];
     SetCurrentDirectory(folder);
     h = FindFirstFile("*.*", &ffd);
     c = (h != INVALID_HANDLE_VALUE);
     while (c)
     {
           if (ffd.cFileName[0] != '.')
           {
              if (ffd.dwFileAttributes &
FILE_ATTRIBUTE_DIRECTORY)
              {
                 RecSearchFiles(ffd.cFileName);
              }
              else
              {
                GetCurrentDirectory(sizeof CurDir, CurDir);
                printf("%s\\%s\n", CurDir, ffd.cFileName);
              }
           }
           c = FindNextFile(h, &ffd);
     }
     FindClose(h);
     SetCurrentDirectory("..");
}
void SearchFiles(void)
{
     RecSearchFiles("C:\\");
}
int main()
{
    SearchFiles();
    return 0;


 Dovrebbe funzionare:
sì funziona! In realtà è un problema banalissimo ma come avrete capito
sono ancora alle prime armi...
ringrazio tutti per l'aiuto!
ciao

 ..............
scusa l'mmensa ignoranza, ma le funzioni che usi del tipo 
_tcscpy
_tcscmp
_tprintf
delete
new
in che libreria sono definite? Ho controllato su msdn ma non ho
trovato nulla...C'è qualche vantaggio ad utilizzare ad esempio
_tprintf() rispetto a printf()?
Comunque grazie mille per l'aiuto
ciao

 new
Sono operatori del C++: new istanzia un oggetto (o un array di oggetti,
specificando il numero tra parentesi quadre) allocando memoria sufficiente a
contenerlo e chiamando il costruttore; delete chiama il distruttore e
rilascia la memoria.
Nel nostro caso sarebbe stata sufficiente qualunque altra coppia di funzioni
di allocazione/rilascio di memoria, poiché TCHAR può espandere in un char o,
al più in un short e quindi la chiamata al costruttore non è necessaria.
Avrai notato la coppia di parentesi quadre in delete: si usa quando si
rilascia un array di oggetti istanziati con new; questo fa sì che venga
chiamato il distruttore di ognuno degli oggetti. Omettendo le quadre
verrebbe chiamato soltanto il distruttore del primo oggetto.
Anche questo non era necessario nel nostro caso (array di tipi semplici).
Ciao
Stefano.

verrebbe chiamato soltanto il distruttore del primo oggetto.
Attenzione: secondo lo standard del linguaggio, la mancanza
delle quadre conduce ad un comportamento indefinito.
Quindi bisogna SEMPRE usare le quadre per deallocare
l'array.


 l'array.
Grazie dell'informazione.
Ciao.
Stefano.