No borrar una carpeta si contiene archivos no cerrados - página 8

 

Más tarde publicaré un script reproduciendo el problema.

Si el problema se resuelve de alguna manera, lo explicaré todo con detalle.

 
Реter Konow:

1. el manejador sólo es necesario para la función FileClose. No abro el archivo. Se creó antes que yo. Simplemente lo copio y lo borro. No puedo cerrarlo porque no hay asa.

2. No se necesita el mango del archivo para copiar (FileCopy), para mover (FileMove). Mira la documentación.

3. si abro un archivo creado por otra persona utilizando la función FileOpen, no obtendré su manejador. No se sabe en absoluto qué asa obtendré. Puede ser el suyo o puede ser uno muy diferente. Intenté obtener el handle del archivo de otra persona para poder cerrar FileClose después de la operación de copia. No funcionó.

4. Al copiar, no se necesita el asa. Se copia sin problemas. Pero el archivo se abre automáticamente para ser copiado. Además, no puedo cerrarlo con FileClose porque no hay asa. Probablemente por eso FolderClean no funciona después de borrar los archivos copiados.

5. ¿Cómo sabes que el archivo no está abierto después de copiarlo? No se abrió explícitamente con la función FileOpen, pero se copió con ella, lo que significa que está abierta. Por lo tanto, sigue abierto después de copiar e incluso después de borrar. Probablemente.

Un manejador de archivo es necesario no sólo para cerrar un archivo, sino también para leer y escribir en un archivo, manejar un puntero de archivo para leer desde una línea específica o escribir en una línea específica. En la documentación se pueden encontrar otras funciones que requieren un manejador de archivo.

2. ¿No podría decirte que para copiar o mover un archivo necesitas un asa para ese archivo? Has entendido algo mal.

Si abres cualquier archivo, no importa por quién o cuándo fue creado, obtienes su handle cuando se ejecuta FileOpen.

Sospecho que no entiendes lo que es un asa. Toma 2 archivos para un experimento, puedes tenerlos listos, puedes abrirlos para escribir y obtener sus asas. Se diferenciarán en uno. A continuación, invierta el orden de apertura de estos archivos y verá las mismas asas, pero pertenecerán a archivos diferentes. Segunda opción: Abrir un archivo, obtener el handle = 1, cerrar ese archivo y abrir otro... y el mango del otro archivo también será =1.

Un handle es la numeración de los archivos dentro del programa y no tiene nada que ver con el contenido del archivo o sus otros atributos.

4. El archivo no se abrirá durante la copia. Y si está copiando leyendo un archivo y escribiendo todo el contenido en otro archivo, los manejadores de esos archivos deben ser puestos en las variables apropiadas para la manipulación posterior de esos archivos.

5. Un archivo puede tardar unos milisegundos en copiarse, exactamente el tiempo que se tarda en guardarlo en el disco. A partir de ahí es tan libre como un pájaro en el cielo... No hay posibilidad de que ocurra nada.

 

Me alegra informar de que el problema está completamente resuelto).

La razón:

Cuando se construye una copia de la jerarquía de archivos en el array, para reproducirla en un navegador de archivos utilizable, una función especial lee esta jerarquía utilizando FileFindFirst() y FileFindNext().

Inicialmente, después de escanear cada carpeta, se llamaba a la función FileFindClose() al final del bucle para cerrar el manejador de búsqueda de cada carpeta específica.

Obviamente, debido a las largas y complejas manipulaciones con la función que lee la jerarquía de archivos, borré accidentalmente esta entrada FileFindClose() y no me di cuenta. No afectó al rendimiento de mi navegador, hasta que empecé a intentar renombrar carpetas. Ahí es donde empezó el problema.

Los archivos, como resultó, no tenían nada que ver con este caso. Por supuesto, es muy útil que haya aprendido que deben estar cerradas, aunque no les haya hecho nada. En el futuro, evitará que cometa los mismos errores.


En general, la razón por la que mi función FolderClean() no funcionaba era que mucho antes de que la utilizara, durante la fase de inicialización del programa, otra función no cerraba los manejadores de búsqueda de FileFindFirst() después de escanear las carpetas.

Resulta que estas cosas están relacionadas...


Hice un script para reproducir el problema, pero por alguna razón en este script, este problema no se reproduce. Es decir, en mi programa añadir/eliminar la línea "FileFindClose(search_handle)" sí afecta al problema, pero en el script, por alguna razón, no.

Adjunto el script a continuación. Cree una carpeta "1" en la carpeta Archivos y coloque allí cualquier otra carpeta o archivo. Si comentas la línea "FileFindClose(search_handle)", el script seguirá borrando la carpeta, pero en mi programa sin esta línea las carpetas no se borran. La razón no está clara.

//+------------------------------------------------------------------+
//|                                             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");
     } 
  }
//+------------------------------------------------------------------+