Una cartella non viene cancellata se contiene file non chiusi - pagina 8

 

Più tardi posterò uno script che riproduce il problema.

Se il problema è in qualche modo risolto, spiegherò tutto in dettaglio.

 
Реter Konow:

1. l'handle è necessario solo per la funzione FileClose. Non apro il file. È stato creato prima di me. Semplicemente lo copio e lo cancello. Non posso chiuderlo perché non c'è una maniglia.

2. L'handle del file non è necessario per copiare (FileCopy), per spostare (FileMove). Guarda la documentazione.

3. se apro un file creato da qualcun altro usando la funzione FileOpen, non ottengo il suo handle. Non si sa affatto quale maniglia avrò. Può essere il suo o può essere un altro. Ho cercato di ottenere l'handle del file di qualcun altro per poterlo chiudere FileClose dopo l'operazione di copia. Non ha funzionato.

4. Quando si copia, la maniglia non è necessaria. Viene copiato senza problemi. Ma il file viene aperto automaticamente per la copia. Inoltre, non posso chiuderlo con FileClose perché non c'è nessun handle. Questo è probabilmente il motivo per cui FolderClean non funziona dopo aver cancellato i file copiati.

5. Come fate a sapere che il file non è aperto dopo la copia? Non è stato aperto esplicitamente dalla funzione FileOpen, ma è stato copiato con, il che significa che è aperto. Quindi rimane aperto dopo la copia e anche dopo la cancellazione. Probabilmente.

Un file handle è necessario non solo per chiudere un file, ma anche per leggere e scrivere su un file, gestire un puntatore di file per leggere da una linea specificata o scrivere su una linea specificata. Altre funzioni che richiedono un handle di file possono essere trovate nella documentazione.

2. Non potevo dirvi che per copiare o spostare un file avete bisogno di un handle per quel file? Hai frainteso qualcosa.

Se si apre un qualsiasi file, non importa da chi o quando è stato creato, si ottiene il suo handle quando viene eseguito FileOpen.

Ho il sospetto che tu abbia frainteso cosa sia una maniglia. Prendete 2 file per un esperimento, potete averli pronti, potete aprirli per scrivere e ottenere le loro maniglie. Essi differiscono di uno. Poi invertite l'ordine di apertura di questi file e vedrete le stesse maniglie, ma apparterranno a file diversi. Seconda opzione: aprire un file, ottenere l'handle = 1, chiudere quel file e aprirne un altro... e anche l'handle dell'altro file sarà =1.

Un handle è la numerazione dei file all'interno del programma e non ha niente a che fare con il contenuto del file o i suoi altri attributi.

4. Il file non sarà aperto durante la copia. E se state copiando leggendo un file e scrivendo l'intero contenuto in un altro file, gli handle di quei file dovrebbero essere messi nelle variabili appropriate per ulteriori manipolazioni di quei file.

5. Un file può richiedere alcuni millisecondi durante la copia, esattamente il tempo necessario per salvarlo su disco. Da lì è libero come un uccello nel cielo... Nessuna possibilità che succeda qualcosa.

 

Sono felice di riferire che il problema è completamente risolto!)

Il motivo:

Quando si costruiva una copia della gerarchia dei file nell'array, per poterla riprodurre in un navigatore di file utilizzabile, una funzione speciale leggeva questa gerarchia usando FileFindFirst() e FileFindNext().

Inizialmente, dopo la scansione di ogni cartella, la funzione FileFindClose() veniva chiamata alla fine del ciclo per chiudere l'handle di ricerca per ogni specifica cartella.

Ovviamente, a causa di lunghe e complesse manipolazioni con la funzione che legge la gerarchia dei file, ho accidentalmente cancellato questa voce FileFindClose() e non me ne sono accorto. Non ha influito sulle prestazioni del mio navigatore, finché non ho iniziato a cercare di rinominare le cartelle. È qui che è iniziato il problema.

I file, come si è scoperto, non c'entrano per niente in questo caso. Certo, è molto utile che io abbia imparato che devono essere chiusi, anche se non gli ho fatto niente. In futuro, mi impedirà di fare gli stessi errori.


In generale, il motivo per cui la mia funzione FolderClean() non ha funzionato è che molto prima che la usassi, durante la fase di inizializzazione del programma, un'altra funzione non è riuscita a chiudere gli handle di ricerca FileFindFirst() dopo la scansione delle cartelle.

Come si è scoperto, queste cose sono collegate...


Ho fatto uno script per riprodurre il problema, ma per qualche motivo in questo script, questo problema non viene riprodotto. Cioè, nel mio programma aggiungere/rimuovere la linea "FileFindClose(search_handle)" influisce sul problema, ma nello script, per qualche motivo, no.

Allego lo script qui sotto. Crea una cartella "1" nella cartella Files e mettici qualsiasi altra cartella o file. Se commentate la linea "FileFindClose(search_handle)", lo script cancellerà comunque la cartella, ma nel mio programma senza questa linea le cartelle non vengono cancellate. La ragione non è chiara.

//+------------------------------------------------------------------+
//|                                             Demo_FolderClean.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//Данный скрипт, сразу после загрузки должен стереть все содержимое 
//папки "1\\" внутри директории "Files".
//Однако, если хэндл поиска, открытый сразу после запуска скрипта функцией
//"FileFindFirst()" не закрыт, то скрипт не сможет стереть папку "1\\".

//Данный скрипт создан для демонстрации взаимосвязи закрытия хэндла поиска
//возвращаемого функцией "FileFindFirst()" и успешной работы функции "FolderClean()".
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   
   //---- Переменная необходимая для функции  "FileFindFirst()" 
   string file_name;
   //-----------------------------
   //Открываем поиск внутри папки "1\\".
   //-----------------------------
   long search_handle=FileFindFirst("1\\",file_name); 
   //--- проверим, успешно ли отработала функция FileFindFirst() 
   if(search_handle!=INVALID_HANDLE) 
     { 
      int i = 0;
      //--- в цикле проверим являются ли переданные строки именами файлов или директорий 
      do 
        { 
         ResetLastError(); 
         //--- если это файл, то функция вернет true, а если директория, то функция генерирует ошибку ERR_FILE_IS_DIRECTORY 
         FileIsExist(file_name); 
         PrintFormat("%d : %s name = %s",i,GetLastError()==ERR_FILE_IS_DIRECTORY ? "Directory" : "File",file_name); 
         i++; 
        } 
      while(FileFindNext(search_handle,file_name)); 
      //--- закрываем хэндл поиска 
      FileFindClose(search_handle); 
     } 
   else 
      Print("Files not found!");/**/ 
   //-----------------------------
   //Переходим к очищению папки "1\\" и ее последующему стиранию.
   //-----------------------------
   if(!FolderClean("1\\"))
   //--- Очищаем папку.
     Print("FolderClean  Error ",GetLastError());
   
   else 
     {//--- Стираем папку.
      if(!FolderDelete("1\\"))
        Print("FolderDelete  Error ",GetLastError());
      
      else 
       Print("Folder was cleaned and removed");
     } 
  }
//+------------------------------------------------------------------+
Motivazione: