Allerdings kannte ich diesen Thread bei Erstellung meiner Funktion nicht und meine bietet
auch etwas mehr.
Es können mehrere Dateien in ein Verzeichnis kopiert werden. Verzeichnisse können nicht kopiert werden.
Es werden wahlweise die Attribute und Daten (Datums?) übertragen. Die Buffergrösse kann bestimmt werden.
Das optionale Callback gibt Dateinamen der aktuellen Datei, den Zielpfad, Gesamtfortschritt in Prozent sowie
Fortschritt der aktuellen Datei wieder.
Weitere Infos im Source.
CopyFilesEx.pbi:
Code: Alles auswählen
; CopyFilesEx
; Version 1.1
; Author: Thomas (ts-soft) Schulz
; erstellt: 27.04.2010
; zuletzt geändert: 28.04.2010
; PB-Version: 4.50 und höher
; Crossplattform (mit kleinen Einschränkungen)
EnableExplicit
Prototype.i CopyFileExCallback(File.s, Dir.s, Sum.f, Procent.f)
; File erhält den Namen der aktuellen Datei
; Dir erhält den Namen des Zielverzeichnisses
; Sum ist der Gesamtforschritt in Prozent
; Procent ist der Fortschritt der aktuellen Datei
; Wenn das Callback #FALSE zurückgibt, wird der Kopiervorgang beendet, anderenfalls fortgesetzt
Structure CopyFilesEx
hWnd.i ; WindowID(#Window) des Fensters, das per Message benachrichtig wird, wenn der Thread fertig ist.
List sourcefiles.s() ; Liste der zu kopierenden Dateien (mit Pfad)
destinationDir.s ; Zielverzeichnis
bufferSize.i ; der zu verwendente Buffersize beim kopieren der Dateien. Sollte auf #PB_Default gesetzt werden (entspricht 4096)
callback.CopyFileExCallback ; ProcedureAdresse des Callbacks für den Fortschritt
Mutex.i ; das Ergebnis von CreateMutex()
pStopVar.i ; Adresse der globalen StopVariable
IgnoreAttribute.b ; auf #True gesetzt, werden Attribute nicht wieder hergestellt
IgnoreDate.b ; auf #True gesetzt, wird Dateidatum nicht wieder hergestellt
EndStructure
; interne Funktion
Procedure.q CopyFileBuffer(sourceID.i, destID.i, buffersize.i)
Protected *mem, result.q
*mem = AllocateMemory(buffersize)
If *mem And IsFile(sourceID) And IsFile(destID)
If Loc(sourceID) + buffersize < Lof(sourceID)
ReadData(sourceID, *mem, buffersize)
WriteData(destID, *mem, buffersize)
result = Loc(destID)
Else
buffersize = Lof(sourceID) - Loc(destID)
If buffersize
ReadData(sourceID, *mem, buffersize)
WriteData(destID, *mem, buffersize)
EndIf
CloseFile(sourceID)
CloseFile(destID)
result = 0
EndIf
FreeMemory(*mem)
EndIf
ProcedureReturn result
EndProcedure
Procedure.i CopyFilesEx(*CFE.CopyFilesEx)
Protected sourceID.i, destID.i, bufferSize.i, position.q, Size.q, Procent.f, cFiles.i, Sum.f, count.i
Protected Attribute.i, Date_Created.i, Date_Accessed.i, Date_Modified.i
If *CFE\Mutex
LockMutex(*CFE\Mutex)
EndIf
cFiles = ListSize(*CFE\sourcefiles())
With *CFE
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
If Right(\destinationDir, 1) <> "\" : \destinationDir + "\" : EndIf ; fehlende Slashes/Backslahes hinzufügen
CompilerElse
If Right(\destinationDir, 1) <> "/" : \destinationDir + "/" : EndIf
CompilerEndIf
If \bufferSize = #PB_Default : \bufferSize = 4096 : EndIf ; standardbuffer grösse
If \bufferSize < 1028 : \bufferSize = 1028 : EndIf ; empfohlene mindestgrösse setzen
EndWith
If FileSize(*CFE\destinationDir) = -2 ; Zielverzeichnis muß existieren
ForEach *CFE\sourcefiles()
With *CFE
If FileSize(\sourcefiles()) >= 0 ; Dateien müssen existieren!
Attribute = GetFileAttributes(\sourcefiles())
Date_Created = GetFileDate(\sourcefiles(), #PB_Date_Created)
Date_Accessed = GetFileDate(\sourcefiles(), #PB_Date_Accessed)
Date_Modified = GetFileDate(\sourcefiles(), #PB_Date_Modified)
sourceID = ReadFile(#PB_Any, \sourcefiles())
If IsFile(sourceID) = #False : Continue : EndIf ; lesen fehlgeschlagen, fortsetzen mit nächstem File.
FileBuffersSize(sourceID, \bufferSize)
Size = Lof(sourceID)
destID = CreateFile(#PB_Any, \destinationDir + GetFilePart(\sourcefiles()))
If IsFile(destID) = #False : CloseFile(sourceID) : Continue : EndIf ; erstellen fehlgeschlagen, fortsetzen mit nächstem File.
FileBuffersSize(destID, \bufferSize)
Sum = (100 * count) / cFiles
count + 1
Repeat
position = CopyFileBuffer(sourceID, destID, \bufferSize)
If \callback <> 0
Procent = (100 * position) / Size
If Not \callback(GetFilePart(\sourcefiles()), \destinationDir, Sum, Procent) Or PeekI(\pStopVar) = #True ; abbrechen gewählt
If IsFile(sourceID) : CloseFile(sourceID) : EndIf
If IsFile(destID) : CloseFile(destID) : EndIf
DeleteFile(\destinationDir + GetFilePart(\sourcefiles()))
Break
EndIf
If position = 0
\callback("", "", 100, 0)
EndIf
EndIf
Until position = 0
If Not \IgnoreAttribute
SetFileAttributes(\destinationDir + GetFilePart(\sourcefiles()), Attribute) ; Attribute wieder herstellen
EndIf
If Not \IgnoreDate
SetFileDate(\destinationDir + GetFilePart(\sourcefiles()), #PB_Date_Created, Date_Created)
SetFileDate(\destinationDir + GetFilePart(\sourcefiles()), #PB_Date_Accessed, Date_Accessed)
SetFileDate(\destinationDir + GetFilePart(\sourcefiles()), #PB_Date_Modified, Date_Modified)
EndIf
DeleteElement(\sourcefiles()) ; erfolgreich kopierte Dateien aus der Liste entfernen um Überprüfung zu ermöglich z.B. bei Abbruch
EndIf
If PeekI(\pStopVar) : Break : EndIf
EndWith
Next
EndIf
If *CFE\Mutex
UnlockMutex(*CFE\Mutex)
EndIf
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
CompilerIf Defined(WM_CopyFileExFinished, #PB_Constant)
If *CFE\hWnd
PostMessage_(*CFE\hWnd, #WM_CopyFileExFinished, 0, 0)
EndIf
CompilerEndIf
CompilerEndIf
EndProcedure
Code: Alles auswählen
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Enumeration #WM_APP
#WM_CopyFileExFinished
EndEnumeration
CompilerEndIf
XIncludeFile "CopyFilesEx.pbi"
Global Stop.i
Procedure FileCallback(File.s, Dir.s, Sum.f, Procent.f)
Static tmpFile.s
Static tmpDir.s
If tmpFile <> File And IsGadget(0)
tmpFile = File
SetGadgetText(0, "Copy File: " + File)
EndIf
If tmpDir <> Dir And IsGadget(1)
tmpDir = Dir
SetGadgetText(1, "To: " + Dir)
EndIf
If IsGadget(2)
SetGadgetState(2, Int(Sum))
EndIf
If IsGadget(3)
SetGadgetState(3, Int(Procent))
EndIf
If Stop
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure OpenProgress()
OpenWindow(0, 0, 0, 400, 160, "Progress CopyFilesEx", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(0, 10, 10, 380, 30, "")
TextGadget(1, 10, 40, 380, 30, "")
ProgressBarGadget(2, 10, 65, 380, 20, 0, 100)
ProgressBarGadget(3, 10, 95, 380, 20, 0, 100)
ButtonGadget(4, 150, 125, 80, 30, "cancel")
EndProcedure
Define.s SPath = PathRequester("Bitte Verzeichnis der zu kopierenden Dateien wählen:", "")
If Not SPath : End : EndIf
Define.s DPath = PathRequester("Bitte Zielordner wählen:", "")
If Not DPath : End : EndIf
Define.i Mutex = CreateMutex()
Define.CopyFilesEx CFE
With CFE
\destinationDir = DPath
\Mutex = Mutex
\bufferSize = #PB_Default
\callback = @FileCallback()
\pStopVar = @Stop
;\IgnoreAttribute = #True
;\IgnoreDate = #True
If ExamineDirectory(0, SPath, "")
While NextDirectoryEntry(0)
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
AddElement(\sourcefiles())
\sourcefiles() = SPath + DirectoryEntryName(0)
EndIf
Wend
FinishDirectory(0)
EndIf
EndWith
OpenProgress()
CFE\hWnd = WindowID(0)
Define.i Thread = CreateThread(@CopyFilesEx(), @CFE)
Repeat
Select WaitWindowEvent()
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Case #WM_CopyFileExFinished
Break
CompilerEndIf
Case #PB_Event_CloseWindow
Stop = #True
WaitThread(Thread)
Break
Case #PB_Event_Gadget
Select EventGadget()
Case 4
Stop = #True
WaitThread(Thread)
Break
EndSelect
EndSelect
ForEver
If ListSize(CFE\sourcefiles())
Debug Str(ListSize(CFE\sourcefiles())) + " Dateien nicht kopiert!"
ForEach CFE\sourcefiles()
Debug CFE\sourcefiles()
Next
EndIf
Gruß
Thomas