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.