닫지 않은 파일이 포함된 폴더는 삭제되지 않습니다. - 페이지 8

 

잠시 후 문제를 재현하는 스크립트를 게시하겠습니다.

문제가 어떻게 든 해결되면 모든 것을 자세히 설명하겠습니다.

 
Реter Konow :

1. 핸들은 FileClose 함수에만 필요합니다. 파일을 열지 않습니다. 그것은 나보다 먼저 창조되었다. 저는 그냥 복사해서 붙여넣습니다. 손잡이가 없어서 닫을 수가 없어요.

2. 복사(FileCopy)의 경우, 이동(FileMove)의 경우 파일 핸들이 필요하지 않습니다. 문서를 보십시오.

3. 이전에 누군가가 FileOpen 함수로 만든 파일을 열면 핸들을 얻지 못합니다. 내가 어떤 핸들을 받을지는 전혀 알려져 있지 않습니다. 그것은 그의 것일 수도 있고 완전히 다를 수도 있습니다. 복사 작업 후 FileClose에 의해 닫히는 방식으로 다른 사람의 파일 핸들을 얻으려고 했습니다. 아무것도.

4. 복사시 손잡이가 필요 없습니다. 문제 없이 복사되었습니다. 그러나 복사를 위해 파일이 자동으로 열립니다. 또한 핸들이 없기 때문에 FileClose 로 닫을 수 없습니다. 복사된 파일을 삭제한 후 FolderClean이 작동하지 않는 이유일 수 있습니다.

5. 복사 후 파일이 열리지 않는다는 것을 어떻게 알 수 있습니까? 이것은 FileOpen 함수에 의해 명시적으로 열리지 않았지만 함께 복사되었으므로 열려 있음을 의미합니다. 따라서 복사 후에도 지워진 후에도 열려 있습니다. 아마.

1. 파일 핸들은 파일을 닫을 때 뿐만 아니라 파일을 읽고 쓰기 위해서도 필요하며, 지정된 라인에서 읽거나 지정된 라인에 쓰기 위해 파일 포인터를 관리합니다. 파일 핸들이 필요한 다른 기능은 설명서에서 찾을 수 있습니다.

2. 파일을 복사하거나 이동하려면 이 파일에 대한 핸들이 필요하다고 말할 수 없었습니까? 당신은 뭔가를 잘못 이해했습니다.

3. 파일을 열면 파일을 만든 사람과 시간에 관계없이 FileOpen 실행 중에 해당 핸들을 얻습니다.

핸들이 무엇인지 잘못 이해하신 것 같습니다. 실험을 위해 2개의 파일을 가져오세요. 준비할 수 있고 쓰기 위해 열어서 핸들을 얻을 수 있습니다. 그들은 하나씩 다를 것입니다. 그런 다음 이러한 파일을 여는 순서를 변경하면 동일한 핸들이 표시되지만 다른 파일에 속하게 됩니다. 두 번째 옵션: 파일 열기, 핸들 =1 가져오기, 이 파일을 닫고 다른 파일 열기... 그러면 이 다른 파일의 핸들도 =1이 됩니다.

핸들은 프로그램 내에서 독점적으로 파일의 번호를 매기고 파일의 내용이나 다른 속성과 연결되지 않습니다.

4. 복사 중에는 파일이 열리지 않습니다. 그리고 한 파일을 읽고 모든 내용을 다른 파일에 쓰는 방식으로 복사하는 경우 이러한 파일에 대한 추가 작업을 위해 이러한 파일의 핸들을 적절한 변수에 넣어야 합니다.

5. 복사하는 동안 파일을 디스크에 저장하는 데 걸리는 시간만큼 파일을 만드는 데 몇 밀리초가 걸릴 수 있습니다. 그러면 그는 하늘을 나는 새처럼 자유로워진다... 확률도 없이.

 

문제가 완전히 해결되었음을 알려드리게 되어 기쁩니다!

원인:

어레이에서 파일 계층의 복사본을 구축할 때 사용자에게 복제합니다. 파일 탐색기, 특수 함수는 FileFindFirst() 및 FileFindNext() 함수를 사용하여 이 계층 구조를 읽습니다.

처음에는 각 폴더의 검색이 완료된 후 루프의 끝에서 FileFindClose() 함수 가 호출되어 각 특정 폴더에 대한 검색 핸들이 닫혔습니다.

분명히, 파일 계층을 읽는 함수로 길고 복잡한 조작의 결과로, 나는 실수로 이 FileFindClose() 항목을 지웠고 그것을 눈치채지 못했습니다. 폴더 이름을 바꾸려고 할 때까지 내비게이터의 작업에는 영향을 미치지 않았습니다. 여기서 문제가 시작되었습니다.

파일은 이 경우 파일과 아무 관련이 없습니다. 물론 수술을 하지 않더라도 강제 폐쇄의 필요성에 대해 알게 된 것은 매우 유용합니다. 앞으로 이것은 비슷한 실수로부터 나를 구할 것입니다.


일반적으로 FolderClean() 함수가 작동하지 않는 이유는 사용하기 훨씬 전에 프로그램 초기화 단계에서도 다른 함수가 폴더 검색 후 FileFindFirst() 함수의 검색 핸들을 닫지 않았기 때문입니다.

그러고 보니 이런 것들이 연결되어...


문제를 재현하기 위해 스크립트를 작성했는데 이 스크립트에서 어떤 이유로 이 문제가 재현되지 않습니다. 즉, 내 프로그램에서 "FileFindClose (search_handle)" 줄을 추가/삭제하면 실제로 문제에 영향을 주지만 스크립트에서는 어떤 이유로 그렇지 않습니다.

아래 스크립트를 첨부합니다. Files 폴더에 "1" 폴더를 만들고 거기에 다른 폴더나 파일을 배치합니다. 스크립트를 로드할 때 폴더를 지워야 합니다. "FileFindClose(search_handle)" 줄을 주석 처리하면 스크립트는 여전히 폴더를 삭제하지만 내 프로그램에서는 이 줄이 없으면 폴더가 삭제되지 않습니다. 이유는 명확하지 않습니다.

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