procedure TurboCopyFile( const SourceFile, (* the source file *) DestinationFile: String; (* destination file *) Display: PProgressbar (* this is a pointer to progress bar which we update if assigned, this procedure can be called without a progress bar like so: TurboCopyFile(Source, Destination, NIL); *) ); type (* define an array of 4096 bytes which holds the bytes *) TurboBuffer = array[1..4096] of Byte; const (* we need to set the size of the buffer in a constant *) szBuffer = sizeof(TurboBuffer); var (* File streams with which we work *) InStream, OutStream: TFileStream; (* we need this to store a logical operation's result *) CanCopy: Boolean; (* holds the number of bytes left when InStream.Size -InStream.Position < 4096 bytes *) BytesLeft: Integer; (* the Buffer almighty *) Buffer: TurboBuffer; begin (* Open the source file so we can read it's bytes *) InStream := TFileStream.Create(SourceFile, fmOpenRead); (* create a new file to the desired destination *) OutStream := TFileStream.Create(DestinationFile, fmCreate); (* check if a progress bar was passed *) if Assigned(Display) then Display^.Max := InStream.Size; (* this is the operation I was talking about in the variable section, this checks if we can read a full buffer(4096 bytes) *) CanCopy := (InStream.Size > InStream.Position) and ((InStream.Size -InStream.Position) >= szBuffer); (* this ensures that the progress bar is being painted *) Application.ProcessMessages; (* loop while we CanCopy *) while CanCopy do begin (* read 4096 bytes from source file *) InStream.ReadBuffer(Buffer, szBuffer); (* then write it to destination file *) OutStream.WriteBuffer(Buffer, szBuffer); (* check if display is assigned *) if Assigned(Display) then (* update it's position *) Display^.Position := InStream.Position; CanCopy := (InStream.Size > InStream.Position) and ((InStream.Size -InStream.Position) >= szBuffer); end; (* store the number of bytes that is less than 4096 into a local variable *) BytesLeft := InStream.Size -InStream.Position; (* do we have some bytes left ? we don't care how many, we just know it's less than 4096 bytes *) if BytesLeft > 0 then begin (* surprise, or not we have some bytes left, read them all into the buffer *) InStream.ReadBuffer(Buffer, BytesLeft); (* write them to destination file *) OutStream.WriteBuffer(Buffer, BytesLeft); end; (* do we have a progress bar ? *) if Assigned(Display) then (* we do? then update it's progress *) Display^.Position := Display^.Max; (* free the memory *) FreeAndNil(InStream); FreeAndNil(OutStream); end; (* end of TurboCopyFile *)
A demo application can be downloaded as
binary
or
sourcecode.
For further reading please refer to :
ReplyDeletehttp://supercopier.sfxteam.org/
;-)
Interesting...
ReplyDeleteHow do you account for a file in use?
ReplyDeleteThis code makes the developer assume that it should copy a file even if in use but because it reads the bytes if the file is in use it causes failure.
well this code does NOT provide too much error handling, if you wish to check if a file is in use you should check out this link.
ReplyDelete