Ein Ordner wird nicht gelöscht, wenn er nicht geschlossene Dateien enthält. - Seite 6

 
Ich habe mich gefragt, was es damit auf sich hat. Wenn ich Zeit habe, werde ich es mir ansehen... Natürlich hätte ich gerne eine präzisere Formulierung der Aufgabe
 
Vladimir Karputov:

Bitte machen Sie weiter - solange Sie in dem faszinierenden Genre der "Fiktion" schreiben. Spätestens auf Seite 40 sind Sie hoffentlich bei der Fachliteratur angelangt.

Der Fehler ist implizit. Im Moment ist es schwierig, mehr technische Details zu nennen.
 
Реter Konow:

Ich habe alle Dateien gelöscht, auch ohne sie explizit zu schließen. Gelöscht, weil ich sie nicht erstellt habe und sie sich vorher im Ordner "Dateien" befanden.

Der Punkt ist, dass wir zum Löschen einer Datei deren Handle benötigen. Wenn wir diese Datei jedoch nicht erstellt, sondern nur in den Ordner "Dateien" gelegt haben, können wir ihr Handle nicht erhalten und sie daher auch nicht mit FileClose() schließen.

Gleichzeitig können wir sie aber immer noch kopieren oder löschen. Allerdings kann der Ordner danach weder programmatisch noch manuell gelöscht werden. Manuell nur nach einem Neustart des Terminals.

Ich werde später versuchen, das Problem anhand von Beispielen deutlicher darzustellen.

Der Code muss nur vollständig sein. Wenn die Datei geöffnet ist, muss sie vor dem Herunterfahren des Computers oder dem Schließen von MT4/5 geschlossen werden. Und vorzugsweise muss der Griff von jeder Stelle des Programms aus zugänglich sein. Dies ist meine Meinung. Noch besser ist es, die Datei sofort zu schließen, nachdem Sie eine Lese-/Schreiboperation mit ihr durchgeführt haben, oder auch wenn Sie nichts mit ihr zu tun haben.

Die Beispieldokumentation scheint zu zeigen, wie man es nicht machen sollte.

Es ist auch sehr wichtig, daran zu denken, dass beim Schreiben in eine Datei die geschriebene Datei nur gelesen werden kann, indem alle im Datei-E/A-Puffer verbliebenen Daten mit FileFlush auf die Festplatte geschrieben werdenoder indem die Datei geschlossen wird. Wenn Sie die Datei schließen, werden die Daten auf die Festplatte zurückgesetzt.

Zusammenfassung: Wenn Sie eine Datei öffnen, vergessen Sie nicht, sie wieder zu schließen. Und der Datei-Handle geht nicht verloren.

Документация по MQL5: Файловые операции / FileFlush
Документация по MQL5: Файловые операции / FileFlush
  • www.mql5.com
Файловые операции / FileFlush - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Alexey Viktorov:

Der Code muss einfach vollständig sein. Wenn eine Datei geöffnet ist, muss sie geschlossen werden, bevor der Computer ausgeschaltet oder MT4/5 geschlossen wird. Und der Griff sollte möglichst von jeder Stelle des Programms aus erreichbar sein. Dies ist IMHO. Noch besser ist es, die Datei sofort nach dem Lese-/Schreibvorgang zu schließen, auch wenn Sie nichts mit ihr zu tun hatten.

Die Beispieldokumentation scheint zu zeigen, wie man es nicht machen sollte.

Es ist auch sehr wichtig, daran zu denken, dass beim Schreiben in eine Datei die geschriebene Datei nur gelesen werden kann, indem alle im Datei-E/A-Puffer verbliebenen Daten mit FileFlush auf die Festplatte geschrieben werdenoder indem die Datei geschlossen wird. Während des Schließvorgangs werden die Daten zwangsweise auf die Festplatte zurückgesetzt.

Zusammenfassung: Wenn Sie eine Datei öffnen, vergessen Sie nicht, sie wieder zu schließen. Und der Datei-Handle geht nicht verloren.

Auch hier kann ich eine von meinem Programm erstellte Datei mit der Funktion FileClose() schließen - ich habe ihr Handle.

Ich kann eine Datei, die von einem anderen Benutzer erstellt wurde, sich aber im Ordner "Dateien" befindet, nicht schließen, weil ich keinen Zugriff darauf habe.

Wenn ich eine Datei kopiere, die nicht von mir erstellt wurde (nicht mein Programm), dann kann ich sie nach dem Kopieren nicht mit der Funktion FileClose() schließen (kein Handle), ABER ich kann sie löschen.

Vielleicht ist das der Grund, warum Ordner mit kopierten und gelöschten Dateien nicht von der Funktion FolderClean() gelöscht werden. Wahrscheinlich, weil sie nicht geschlossen wurden, nachdem sie kopiert worden waren.

ABER SIE KÖNNEN NICHT GESCHLOSSEN WERDEN, WEIL SIE KEINEN GRIFF HABEN!

:)))

 

Fragen an die Entwickler:

1. Wie erhalte ich den Handle der Datei, die vor dem Laden des Skripts im Ordner "Files" erstellt wurde?

2. Könnte das Problem des Löschens von Ordnern mit FolderClean(), nachdem Dateien darin gelöscht wurden, die zuvor in einen anderen Ordner kopiert und nach dem Kopieren nicht geschlossen wurden (weil es keinen Handle gibt), die oben genannte Ursache haben?

 
Реter Konow:

Fragen an die Entwickler:

1. Wie erhalte ich den Handle der Datei, die vor dem Laden des Skripts im Ordner "Files" erstellt wurde?

2. Könnte das Problem des Löschens von Ordnern mit der Funktion FolderClean(), nachdem Dateien darin gelöscht wurden, die zuvor in einen anderen Ordner kopiert und nach dem Kopieren nicht geschlossen wurden (weil es keinen Handle gibt), den oben genannten Grund haben?


Das sind sozusagen die Grundlagen des Betriebssystems. Wenn eine Anwendung eine Datei zum Schreiben geöffnet hat, kann weder diese Datei noch der Ordner, der sie enthält, gelöscht werden. Versuchen Sie, eine Datei in Word zu öffnen und dann mit den Werkzeugen des Betriebssystems den Ordner zu löschen, in dem sie sich befindet. Was wird geschehen? Das werden Sie nicht können, weil Sie keinen Zugang dazu haben werden.

Nun, Sie können den Datei-Handle bekommen. Aber was würde eine solche Aktion bringen? Denn wenn die Datei von einer anderen Anwendung geöffnet wird, sehen Sie die vorherige Anweisung. Wir erhalten nur ein Handle, das in unserer Anwendung gültig ist.

 
Ihor Herasko:

Das sind sozusagen die Grundlagen des Betriebssystems. Wenn eine Anwendung eine Datei zum Schreiben geöffnet hat, können weder die Datei noch der Ordner, der sie enthält, gelöscht werden. Versuchen Sie, eine Datei in Word zu öffnen und dann mit Hilfe des Betriebssystems den Ordner zu löschen, in dem sie sich befindet. Was wird geschehen? Das werden Sie nicht können, weil Sie keinen Zugang dazu haben werden.

Nun, Sie können den Datei-Handle bekommen. Aber was würde eine solche Maßnahme bringen? Denn wenn die Datei von einer anderen Anwendung geöffnet wird, sehen Sie die vorherige Anweisung. Und wir können nur einen Handle erhalten, der in unserer speziellen Anwendung gültig ist.

Die Datei wird von meiner Anwendung (Datei-Navigator) geöffnet, um in einen anderen Ordner überschrieben zu werden.

Nach dem Überschreiben muss ich die Datei schließen, kann das aber nicht (kein Handle), also lösche ich die Datei einfach.

Es gibt keinen Handle, da nicht bekannt ist, wann und von wem die Datei erstellt wurde.

Gleichzeitig existiert die Datei im Ordner "Dateien" und kann in einen anderen Ordner kopiert und dann gelöscht werden.

Nach dem Kopieren kann die Datei jedoch nicht geschlossen werden. Es gibt keinen Griff.

Dies ist wahrscheinlich der Grund, warum das weitere Löschen von Ordnern mit FolderClean() mit gelöschten Dateien nicht funktioniert.


Frage: Wie bekomme ich das Handle dieser Datei in das MQL-Programm?

 

Dies scheint ein Problem zu sein, mit dem die Gemeinschaft noch nicht konfrontiert wurde... :)

OK, ich werde mir etwas einfallen lassen.

Das tue ich immer.)

 

Entlarvung von Mythen.

Also, Terminaldaten auf dem Betriebssystem:

2017.08.28 22:20:53.474 Terminal        MetaTrader 5 x64 build 1653 started (MetaQuotes Software Corp.)
2017.08.28 22:20:53.476 Terminal        Windows 10 Pro (x64 based PC), IE 11.00, UAC, Intel Core i3-3120 M  @ 2.50 GHz, RAM: 4830 / 8077 Mb, HDD: 315702 / 475588 Mb, GMT+02:00
2017.08.28 22:20:53.476 Terminal        C:\Users\barab\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075

Zum Zeitpunkt der Tests wurde der Ordner "test" in [data folder]\MQL5\Files erstellt und darin die Textdatei "source.txt" mit folgendem Inhalt angelegt:

FileCopy
The function copies the original file from a local or shared folder to another file.
bool  FileCopy( 
   const string  src_file_name,     // Name of a source file 
   int           common_flag,       // Location 
   const string  dst_file_name,     // Name of the destination file 
   int           mode_flags         // Access mode 
   );


Schritt 1: Kopieren der Datei "source.txt" in eine andere Datei mit den MQL5-Tools

Drehbuch:

//--- display the window of input parameters when launching the script 
#property script_show_inputs 
//--- input parameters 
input string InpSrc="test\\source.txt";       // source 
input string InpDst="test\\destination.txt";  // copy 
input int    InpEncodingType=FILE_ANSI; // ANSI=32 or UNICODE=64 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart()
  {
//--- display the source contents (it must exist) 
   if(!FileDisplay(InpSrc))
      return;
//--- check if the copy file already exists (may not be created) 
   if(!FileDisplay(InpDst))
     {
      //--- the copy file does not exist, copying without FILE_REWRITE flag (correct copying) 
      if(FileCopy(InpSrc,0,InpDst,0))
         Print("File is copied!");
      else
         Print("File is not copied!");
     }
   else
     {
      //--- the copy file already exists, try to copy without FILE_REWRITE flag (incorrect copying) 
      if(FileCopy(InpSrc,0,InpDst,0))
         Print("File is copied!");
      else
         Print("File is not copied!");
      //--- InpDst file's contents remains the same 
      FileDisplay(InpDst);
      //--- copy once more with FILE_REWRITE flag (correct copying if the file exists) 
      if(FileCopy(InpSrc,0,InpDst,FILE_REWRITE))
         Print("File is copied!");
      else
         Print("File is not copied!");
     }
//--- receive InpSrc file copy 
   FileDisplay(InpDst);
  }
//+------------------------------------------------------------------+ 
//| Read the file contents                                           | 
//+------------------------------------------------------------------+ 
bool FileDisplay(const string file_name)
  {
//--- reset the error value 
   ResetLastError();
//--- open the file 
   int file_handle=FileOpen(file_name,FILE_READ|FILE_WRITE|FILE_TXT|InpEncodingType);
   if(file_handle!=INVALID_HANDLE)
     {
      //--- display the file contents in the loop 
      Print("+---------------------+");
      PrintFormat("File name = %s",file_name);
      while(!FileIsEnding(file_handle))
         Print(FileReadString(file_handle));
      Print("+---------------------+");
      //--- close the file 
      FileClose(file_handle);
      return(true);
     }
//--- failed to open the file 
   PrintFormat("%s is not opened, error = %d",file_name,GetLastError());
   return(false);
  }
//+------------------------------------------------------------------+


Schritt 2: Bereinigung des Ordners "test" mit MQL5-Tools

Drehbuch:

//+------------------------------------------------------------------+
//|                                                  FolderClean.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//--- Description 
#property description "The script shows a sample use of FolderClean()." 
//--- Show the dialog of input parameters when starting the script 
#property script_show_inputs 
//--- Input parameters 
input string   foldername="test";  // folder in MQL5/Files/ 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart()
  {
//--- Start to delete files 
   PrintFormat("Trying to delete all files from folder %s",foldername);
   if(FolderClean(foldername,0))
      PrintFormat("Files have been successfully deleted, %d files left in folder %s",
                  foldername,
                  FilesInFolder(foldername+"\\*.*",0));
   else
      PrintFormat("Failed to delete files from folder %s. Error code %d",foldername,GetLastError());
//--- 
  }
//+------------------------------------------------------------------+ 
//| Returns the number of files in the specified folder              | 
//+------------------------------------------------------------------+ 
int FilesInFolder(string path,int flag)
  {
   int count=0;
   long handle;
   string filename;
//--- 
   handle=FileFindFirst(path,filename,flag);
//--- If at least one file found, search for more files 
   if(handle!=INVALID_HANDLE)
     {
      //--- Show the name of the file 
      PrintFormat("File %s found",filename);
      //--- Increase the counter of found files/folders 
      count++;
      //--- Start search in all files/folders  
      while(FileFindNext(handle,filename))
        {
         PrintFormat("File %s found",filename);
         count++;
        }
      //--- Do not forget to close the search handle upon completion 
      FileFindClose(handle);
     }
   else // Failed to get the handle 
     {
      PrintFormat("Files search in folder %s failed",path);
     }
//--- Return the result 
   return count;
  }
//+------------------------------------------------------------------+


Schritt 3: Löschen des Ordners "test" mit den MQL5-Tools

//+------------------------------------------------------------------+
//|                                                 FolderDelete.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//--- Description 
#property description "The script shows a sample use of FolderDelete()." 
#property description "First two folders are created; one of them is empty, the second one contains a file." 
#property description "When trying to delete a non-empty folder, an error is returned and a warning is shown."

//--- Show the dialog of input parameters when starting the script 
#property script_show_inputs 
//--- Input parameters 
input string   InpFolder="test";     // An empty folder 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart()
  {
//--- Delete the comment form the chart 
   Comment("");
//--- Add a message into the "Experts" journal 
   PrintFormat("Trying to delete folder %s",InpFolder);
   ResetLastError();
//--- Delete the empty folder 
   if(FolderDelete(InpFolder))
      //--- The following message should appear since the folder is empty 
      PrintFormat("Folder %s has been successfully deleted",InpFolder);
   else
      PrintFormat("Failed to delete folder %s. Error code=%d",InpFolder,GetLastError());
//--- 
  }
//+------------------------------------------------------------------+


Wo liegt das Problem? Alles funktioniert.

Dateien:
 
Vladimir Karputov:

Was ist denn so schlimm daran? Alles funktioniert.

Vielen Dank für dieses Beispiel. Ich werde es morgen früh herausfinden. Ich habe im Moment nicht die Energie dafür).

Ich werde alles prüfen und Ihnen eine Antwort geben.


Hinzugefügt:

Sie haben hier drei verschiedene Skripte zitiert.

Ich habe ein Programm und das Kopieren, Löschen von Dateien und Ordnern geschieht innerhalb einer Funktion in zwei Zyklen.

Geben Sie den ersten Zyklus ein: Zuerst werden die Quelldateien in einen anderen Ordner kopiert, dann werden diese Quelldateien gelöscht. Beenden Sie den ersten Zyklus.

Wir beginnen mit der zweiten Schleife: Wir leeren den Quellordner mit FolderClean() und löschen den Quellordner mit -FolderDelete().


Dann sehen wir im Dateinavigator des Meta-Editors, dass der Quellordner teilweise gelöscht wurde. Unterordner, die keine Dateien enthielten, wurden vollständig gelöscht, und diejenigen, die einige Dateien enthielten, wurden nicht gelöscht, sondern sind leer.

Versuchen Sie, Ordner manuell zu entfernen - wir haben es geschafft:



Dann schließen wir das Terminal und starten es erneut. Wir sehen, dass einige Unterordner von selbst verschwunden sind, andere sind geblieben. Wir löschen sie manuell und ohne Probleme. Dieses Mal.