Kopierfunktion mit Fortschrittsanzeige



  • Hallo,
    ich möchte beim kopieren von Dateien eine Fortschrittsanzeige haben.
    Dafür benutze ich folgende Funktion:

    int ExtFileCopy(AnsiString slSourceFile, AnsiString slDestFile,double dlUpdateInterval, pfUpdateStatus plFunc)
    {
      int ilBufSize = 1024;                // Puffer-Grösse
      bool blRetVal = false;               // Rückgabewert
      int ilSourceHandle, ilDestHandle;    // Dateien-Handles
      DWORD ilFileSize = 0;                // Dateigrösse
      DWORD ilBytesTotal = 0;              // Anz. der bereits kopierten Bytes
      int ilBytesLastWrite = 0;            // Anz. der im aktuellen
                                           // Schleifendurchlauf kopierten Bytes
      double dlLastValue = 0;              // zuletzt ausgegebener Fortschrittswert
      int ilBytes = 0;                     // Anz. der in Lesepuffer eingelesenen
    									   // Bytes
    
      // Falls ein Verzeichnis als Name der Zieldatei übergeben, Namen der
      // Quelldatei an den Verzeichnisnamen anhängen:
      int ilAttr = FileGetAttr(slDestFile);
      if (ilAttr != -1 && ilAttr & faDirectory)
        slDestFile = IncludeTrailingBackslash(slDestFile) +
          ExtractFileName(slSourceFile);
    
      // Falls Namen der Ziel- und Quelldatei identisch, abbrechen:
      if(!slDestFile.AnsiCompareIC(slSourceFile)) return false;
    
      // Quelldatei öffnen:
      ilSourceHandle = FileOpen(slSourceFile.c_str(),fmOpenRead);
      if(ilSourceHandle >= 0)
      {
        // Die Dateigrösse ermitteln:
    	ilFileSize = GetFileSize((HANDLE)ilSourceHandle, NULL);
        if(ilFileSize != 0xFFFFFFFF)
        {
    	  // Anzeige zurücksetzen:
          if(plFunc != NULL)
          {
    		plFunc(0.0, 0, ilFileSize);
    		Application->ProcessMessages();
          }
    
          // Zieldatei öffnen:
          ilDestHandle = FileCreate(slDestFile.c_str());
    	  if(ilDestHandle >= 0)
          {
            // Schreib- / Lesepuffer erzeugen:
    		char *cpBuffer = new char[ilBufSize];
            if(cpBuffer)
            {
    		  blRetVal = true;
    
              while(ilBytesTotal < ilFileSize)
    		  {
                // Daten aus der Quelldatei in den Puffer einlesen:
                ilBytes = FileRead(ilSourceHandle, cpBuffer, ilBufSize);
    
                // Fehler aufgetreten:
                if (ilBytes == -1) blRetVal = false;
    			// Falls Daten eingelesen:
                else if (ilBytes != 0)
                {
    			  // Daten aus dem Puffer in die Zieldatei schreiben:
                  ilBytesLastWrite = FileWrite(ilDestHandle, cpBuffer, ilBytes);
                  ilBytesTotal += ilBytesLastWrite;
    			  // Falls Anz. der gelesenen Bytes != der Anz. der geschr:
                  if(ilBytes != ilBytesLastWrite) blRetVal = false;
    			}
    			// Fortschritt anzeigen:
    			if(plFunc != NULL && (double(ilBytesTotal)*100.0/
    			   double(ilFileSize)>=dlLastValue + dlUpdateInterval ||
    			   ilBytes != ilBytesLastWrite || ilBytesTotal == ilFileSize))
    			{
    			  // Falls in Prozent von Dateigrösse ausgeben:
    			  plFunc(double(ilBytesTotal)*100.0/double(ilFileSize),
    				ilBytesTotal, ilFileSize);
    			  dlLastValue = double(ilBytesTotal)*100.0/double(ilFileSize);
    			}
    			Application->ProcessMessages();
    			if(!blRetVal) break;
    		  }
    		  delete [] cpBuffer;
    		}
    
    		// Falls keine Fehler aufgetreten
    		if(blRetVal)
    		{
    		  // Zeitstempel übernehmen:
    		  FileSetDate(ilDestHandle, FileGetDate(ilSourceHandle));
    
    		  // Dateien schliessen:
    		  FileClose(ilSourceHandle);
    		  FileClose(ilDestHandle);
    		}
    		else
    		{
    		  // Dateien schliessen:
    		  FileClose(ilSourceHandle);
    		  FileClose(ilDestHandle);
    		  // Dateiteile ggf. entfernen:
    		  DeleteFile(slDestFile);
    		}
    	  }
    	}
    	else FileClose(ilSourceHandle);
      }
      return blRetVal;
    }
    

    "pfUpdateStatus plFunc" ist die Funktion, die den Fortschritt in der Progressbar anzeigt.
    Funktioniert auch alles recht hübsch. Nur die Geschwindigkeit hinkt ziemlich hinterher. Von Hand kopieren geht so ungefähr doppelt so schnell.
    Kann ich das irgendwie optimieren (ilBufSize) oder gibt es da andere Lösungsansätze ?

    Danke



  • Hallo

    Versuch gar nicht erst, das Betriebssystem zu schlagen. Verwende CopyFileEx. Dieser Funktion kannst du eine CallBack-Funktion übergeben, um dir den Fortschritt melden lassen.

    bis bald
    akari



  • Oder noch besser: SHFileOperation, die zeigt den Fortschrittsdialog gleich mit an



  • Oder schreib dir eine eigene Funktion in Assembler. 🕶


Anmelden zum Antworten