lazarus-ccr/examples/germesorders/U_ExtFileCopy.pas
MageSlayer 05a5e2c6a2 First public commit
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@639 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2008-12-21 21:46:28 +00:00

479 lines
16 KiB
ObjectPascal

unit U_ExtFileCopy;
{$mode objfpc}{$H+}
{
Composant TExtFileCopy
Développé par:
Matthieu GIROUX
Composant non visuel permettant de copier un fichier plus rapidement
que par le fonction copy de windows.
Compatible Linux
Attention: La gestion de la RAM étant calamiteuse sous Win9x, l'
utilisation de ce composant provoque une grosse une forte baisse de la
mémoire disponible. Sous WinNT/2000 il n' y a pas de problèmes
Version actuelle: 1.0
Mises à jour:
}
interface
uses
SysUtils, Classes,ComCtrls, StrUtils, lresources ;
var GS_COPYFILES_ERROR_DIRECTORY_CREATE : String = 'Erreur à la création du répertoire' ;
GS_COPYFILES_ERROR_IS_FILE : String = 'Ne peut copier dans le fichier' ;
GS_COPYFILES_ERROR_CANT_COPY : String = 'Impossible de copier ' ;
GS_COPYFILES_ERROR_PARTIAL_COPY : String = 'Copie partielle du fichier ' ;
GS_COPYFILES_ERROR_PARTIAL_COPY_SEEK: String = 'Erreur à la copie partielle du fichier ' ;
GS_COPYFILES_ERROR_CANT_READ : String = 'Impossible de lire le fichier ' ;
GS_COPYFILES_ERROR_CANT_CHANGE_DATE : String = 'Impossible d''affecter la date au fichier ' ;
GS_COPYFILES_ERROR_CANT_CREATE : String = 'Impossible de créer le fichier ' ;
GS_COPYFILES_ERROR_CANT_APPEND : String = 'Impossible d''ajouter au fichier ' ;
GS_COPYFILES_ERROR_FILE_DELETE : String = 'Impossible d''effacer le fichier ' ;
GS_COPYFILES_CONFIRM_FILE_DELETE : String = 'Voulez-vous effacer le fichier ' ;
GS_COPYFILES_CONFIRM : String = 'Demande de confirmation' ;
type
TECopyOption = ( cpCopyAll, cpUseFilter, cpNoStructure, cpCreateBackup, cpCreateDestination, cpDestinationIsFile );
TECopyOptions = set of TECopyOption;
TECopyEvent = procedure(Sender : Tobject; const BytesCopied,BytesTotal : cardinal) of object;
TEReturnEvent = procedure(Sender : Tobject; var Continue : Boolean ) of object;
TECopyErrorEvent = procedure(Sender : Tobject; const ErrorCode : Integer ; var ErrorMessage : AnsiString ; var ContinueCopy : Boolean ) of object;
TECopyFinishEvent = procedure(Sender : Tobject; const ASource, ADestination : AnsiString ; const Errors : Integer ) of object;
TEChangeDirectoryEvent = procedure(Sender : Tobject; const NewDirectory, DestinationDirectory : AnsiString ) of object;
const
lco_Default = [cpCopyAll,cpUseFilter];
CST_COPYFILES_ERROR_IS_READONLY = faReadOnly ;
CST_COPYFILES_ERROR_UNKNOWN = -1 ;
CST_COPYFILES_ERROR_IS_DIRECTORY = faDirectory ;
CST_COPYFILES_ERROR_IS_FILE = 1 ;
CST_COPYFILES_ERROR_DIRECTORY_CREATE = 2 ;
CST_COPYFILES_ERROR_CANT_COPY = 3 ;
CST_COPYFILES_ERROR_CANT_READ = 4 ;
CST_COPYFILES_ERROR_CANT_CREATE = 5 ;
CST_COPYFILES_ERROR_CANT_APPEND = 6 ;
CST_COPYFILES_ERROR_FILE_DELETE = 7 ;
CST_COPYFILES_ERROR_PARTIAL_COPY = 8 ;
CST_COPYFILES_ERROR_PARTIAL_COPY_SEEK = 9 ;
CST_COPYFILES_ERROR_CANT_CHANGE_DATE = 10 ;
type
{ TExtFileCopy }
TExtFileCopy = class(TComponent)
private
FOnChange : TEChangeDirectoryEvent ;
FSizeTotal : Int64 ;
FErrors ,
FSizeProgress : Integer ;
FOnSuccess : TECopyFinishEvent;
FOnFailure : TECopyErrorEvent ;
FBeforeCopy : TEReturnEvent ;
FBeforeCopyBuffer ,
FOnProgress : TECopyEvent;
FBufferSize : integer;
FOptions : TECopyOptions ;
FFilter, FSource,FDestination : string;
FInProgress : Boolean;
procedure SetBufferSize (Value : integer);
procedure SetDestination(Value : String);
procedure SetSource(Value: String);
protected
FBuffer : array[0..65535] of char;
function BeforeCopyBuffer ( var li_SizeRead, li_BytesTotal : Longint ) : Boolean ; virtual ;
function BeforeCopy : Boolean ; virtual ;
procedure AfterCopyBuffer ; virtual ;
{ Déclarations protégées }
public
function EventualFailure ( const ai_Error : Integer ; as_Message : AnsiString ):Boolean; virtual ;
function InternalDefaultCopyFile ( const as_Source, as_Destination : String ):Boolean; virtual ;
procedure InternalFinish ( const as_Source, as_Destination : String ); virtual ;
constructor Create(AOwner : Tcomponent);override;
property InProgress : Boolean read FInprogress;
Function CopyFile ( const as_Source, as_Destination : String ; const ab_AppendFile, ab_CreateBackup : Boolean ):Integer;
Procedure CopySourceToDestination;
published
property BufferSize : integer read FBufferSize write SetBufferSize default 65536;
property Source : string read FSource write SetSource;
property Mask : string read FFilter write FFilter;
property Destination : string read FDestination write SetDestination;
property Options : TECopyOptions read FOptions write FOptions default lco_Default ;
property OnSuccess : TECopyFinishEvent read FOnSuccess write FOnSuccess;
property OnFailure : TECopyErrorEvent read FOnFailure write FOnFailure;
property OnProgress : TECopyEvent read FOnProgress write Fonprogress;
property OnBeforeCopyBuffer : TECopyEvent read FBeforeCopyBuffer write FBeforeCopyBuffer;
property OnBeforeCopy : TEReturnEvent read FBeforeCopy write FBeforeCopy;
property OnChange : TEChangeDirectoryEvent read FOnChange write FOnChange;
end;
{TExtFilePartialCopy}
TExtFilePartialCopy = class(TExtFileCopy)
private
lb_ExcludedFound : Boolean ;
lpch_excludeStart,
lpch_excludeEnd : String ;
FExcludeStart ,
FExcludeEnd : String ;
FExcludeReading : Boolean;
protected
function BeforeCopyBuffer ( var li_SizeRead, li_BytesTotal : Longint ) : Boolean ; override ;
function BeforeCopy : Boolean ; override ;
procedure AfterCopyBuffer ; override ;
{ Déclarations protégées }
public
constructor Create(AOwner : Tcomponent);override;
published
property ExcludeReading : Boolean read FExcludeReading write FExcludeReading default False ;
property ExcludeStart : String read FExcludeStart write FExcludeStart ;
property ExcludeEnd : String read FExcludeEnd write FExcludeEnd ;
end;
procedure Register;
implementation
uses functions_file, Forms, Dialogs, Controls ;
{TExtFileCopy}
constructor TExtFileCopy.Create(AOwner :Tcomponent);
begin
inherited Create(AOwner);
Options := lco_Default ;
FBufferSize := 65536;
FInProgress := False;
end;
procedure TExtFileCopy.SetBufferSize(Value : integer);
begin
If not FInprogress
then
begin
If Value > high ( FBuffer )
then
Value := high ( FBuffer ) + 1
Else
FBufferSize := Value;
end;
end;
procedure TExtFileCopy.SetDestination(Value: String);
begin
if FDestination <> Value Then
Begin
FDestination := Value;
End;
end;
procedure TExtFileCopy.SetSource(Value: String);
begin
if FSource <> Value Then
Begin
FSource := Value;
if not ( csDesigning in ComponentState )
and Assigned ( @FOnChange )
Then
FOnChange ( Self, FSource, FDestination );
End;
end;
function TExtFileCopy.BeforeCopyBuffer(var li_SizeRead, li_BytesTotal : Longint ): Boolean;
begin
Result := True ;
if Assigned ( FBeforeCopyBuffer ) Then
FBeforeCopyBuffer ( Self, li_SizeRead, li_BytesTotal );
end;
function TExtFileCopy.BeforeCopy: Boolean;
begin
Result := True ;
if Assigned ( FBeforeCopy ) Then
FBeforeCopy ( Self, Result );
end;
procedure TExtFileCopy.AfterCopyBuffer;
begin
end;
Function TExtFileCopy.CopyFile ( const as_Source, as_Destination : String ; const ab_AppendFile, ab_CreateBackup : Boolean ):Integer;
var
li_SizeRead,li_SizeWrite,li_TotalW, li_RealTotal : Longint;
li_SizeTotal : Int64 ;
li_HandleSource,li_HandleDest, li_pos, li_Confirm : integer;
ls_FileName, ls_FileExt,ls_Destination : String ;
lb_FoundFile : Boolean;
lsr_data : Tsearchrec;
begin
Result := 0 ;
li_Confirm := mrYes ;
FindFirst(as_Source,faanyfile,lsr_data);
li_RealTotal := lsr_data.size ;
li_SizeTotal := lsr_data.Size;
inc ( FSizeTotal, li_SizeTotal );
li_TotalW := 0;
findclose(lsr_data);
try
li_HandleSource := fileopen(as_Source,fmopenread);
Except
On E: Exception do
Begin
Result := CST_COPYFILES_ERROR_CANT_READ ;
EventualFailure ( Result, GS_COPYFILES_ERROR_CANT_READ + as_Destination );
Exit ;
End ;
End ;
ls_Destination := as_Destination ;
if ab_AppendFile
and fileexists(as_Destination)
then
try
FindFirst(as_Destination,faanyfile,lsr_data);
li_HandleDest := FileOpen(as_Destination, fmopenwrite );
FileSeek ( li_HandleDest, lsr_data.Size, 0 );
findclose(lsr_data);
Except
Result := CST_COPYFILES_ERROR_CANT_APPEND ;
EventualFailure ( Result, GS_COPYFILES_ERROR_CANT_APPEND + as_Destination );
Exit ;
End
Else
Begin
If fileexists(ls_Destination)
then
Begin
FindFirst(as_Destination,faanyfile,lsr_data);
if ( ab_CreateBackup )
Then
try
ls_FileName := lsr_data.Name;
ls_FileExt := '' ;
li_pos := 1;
while ( PosEx ( '.', ls_FileName, li_pos + 1 ) > 0 ) Do
li_pos := PosEx ( '.', ls_FileName, li_pos + 1 );
if ( li_Pos > 1 ) Then
Begin
ls_FileExt := Copy ( ls_FileName, li_pos, length ( ls_FileName ) - li_pos + 1 );
ls_FileName := Copy ( ls_FileName, 1, li_pos - 1 );
End ;
li_pos := 0 ;
while FileExists ( ls_Destination ) do
Begin
inc ( li_pos );
ls_Destination := ExtractFilePath ( as_Destination ) + DirectorySeparator + ls_FileName + '-' + IntToStr ( li_pos ) + ls_FileExt ;
End
Except
Result := -1 ;
EventualFailure ( Result, as_Destination );
Exit ;
End
Else
try
if li_Confirm <> mrAll Then
li_Confirm := MessageDlg ( GS_COPYFILES_CONFIRM, GS_COPYFILES_CONFIRM_FILE_DELETE, mtConfirmation, [mbYes,mbNo,mbAll,mbCancel], 0 );
if li_Confirm = mrCancel Then
Abort ;
if li_Confirm = mrNo Then
Exit ;
Deletefile(as_Destination);
Except
Result := CST_COPYFILES_ERROR_FILE_DELETE ;
EventualFailure ( Result, GS_COPYFILES_ERROR_FILE_DELETE + as_Destination );
Exit ;
End ;
findclose(lsr_data);
End ;
try
li_HandleDest := filecreate(ls_Destination);
Except
Result := CST_COPYFILES_ERROR_CANT_CREATE ;
EventualFailure ( Result, GS_COPYFILES_ERROR_CANT_CREATE + as_Destination );
Exit ;
End
end ;
if not BeforeCopy Then
Exit ;
lb_FoundFile := False;
while not lb_FoundFile do
try
li_SizeRead := FileRead(li_HandleSource,FBuffer,FbufferSize);
if ( li_SizeRead <= 0 )
and ( li_TotalW < li_RealTotal )
Then
try
FileSeek ( li_HandleSource, 64, li_TotalW );
Inc ( li_TotalW, 64 );
Continue ;
Except
Result := CST_COPYFILES_ERROR_PARTIAL_COPY_SEEK ;
EventualFailure ( Result, GS_COPYFILES_ERROR_PARTIAL_COPY_SEEK + as_Destination );
End ;
if BeforeCopyBuffer ( li_SizeRead, li_TotalW ) Then
Begin
li_SizeWrite := Filewrite(li_HandleDest,Fbuffer,li_SizeRead);
Application.ProcessMessages;
inc( li_TotalW, li_SizeWrite );
if ( li_SizeRead < FBufferSize )
and ( li_TotalW >= li_RealTotal )
then
lb_FoundFile := True;
if li_SizeWrite < li_SizeRead
then
Begin
Result := CST_COPYFILES_ERROR_PARTIAL_COPY ;
EventualFailure ( Result, GS_COPYFILES_ERROR_PARTIAL_COPY + as_Destination );
End ;
if assigned(FonProgress) then FonProgress(self, FSizeProgress + li_TotalW,FSizeTotal);
End ;
AfterCopyBuffer ;
Except
Result := CST_COPYFILES_ERROR_CANT_COPY ;
EventualFailure ( Result, GS_COPYFILES_ERROR_CANT_COPY + '( ' + as_Source + ' -> ' + as_Destination + ' )' );
Exit ;
End ;
try
filesetdate(li_HandleDest,filegetdate(li_HandleSource));
Except
Result := CST_COPYFILES_ERROR_CANT_CHANGE_DATE ;
EventualFailure ( Result, GS_COPYFILES_ERROR_CANT_CHANGE_DATE + as_Destination );
Exit ;
End ;
fileclose(li_HandleSource);
fileclose(li_HandleDest);
if Result = 0 then
Begin
inc ( FSizeProgress, li_TotalW );
InternalFinish ( as_Source, as_Destination );
Result := 0 ;
End ;
Application.ProcessMessages ;
end;
function TExtFileCopy.InternalDefaultCopyFile ( const as_Source, as_Destination : String ):Boolean;
var li_Error : Integer ;
begin
Result := True ;
li_Error := CopyFile ( as_Source, as_Destination, cpDestinationIsFile in FOptions, cpCreateBackup in FOptions );
EventualFailure ( li_Error , '' );
End ;
function TExtFileCopy.EventualFailure ( const ai_Error : Integer ; as_Message : AnsiString ):Boolean;
begin
Result := True ;
if ( ai_Error <> 0 ) then
Begin
inc ( FErrors );
if assigned ( FOnFailure ) then
Begin
FOnFailure ( Self, ai_Error, as_Message, Result );
End ;
End ;
End ;
procedure TExtFileCopy.InternalFinish ( const as_Source, as_Destination : String );
begin
if assigned ( @FOnSuccess ) then
Begin
FOnSuccess ( Self, as_Source, as_Destination, FErrors );
End ;
End ;
procedure TExtFileCopy.CopySourceToDestination;
var
lb_Continue : Boolean ;
begin
Finprogress := true;
FSizeTotal := 0 ;
FErrors := 0 ;
FSizeProgress := 0 ;
if ( not FileExists ( FSource )
and not DirectoryExists ( FSource ))
Then
Exit ;
if not DirectoryExists ( FDestination )
and not fb_CreateDirectoryStructure ( FDestination )
Then
Exit ;
try
if ( DirectoryExists ( FSource )) Then
Begin
lb_Continue := fb_InternalCopyDirectory ( FSource, FDestination, FFilter, not ( cpNoStructure in FOptions ), cpDestinationIsFile in FOptions, cpCopyAll in FOptions, cpCreateBackup in FOptions, Self );
End
Else
Begin
lb_Continue := fb_InternalCopyFile ( FSource, FDestination, cpDestinationIsFile in FOptions, cpCreateBackup in FOptions, Self );
End ;
finally
FinProgress := false;
End ;
end;
{TExtFilePartialCopy}
constructor TExtFilePartialCopy.Create(AOwner :Tcomponent);
begin
inherited Create(AOwner);
FExcludeReading := False ;
end;
function TExtFilePartialCopy.BeforeCopyBuffer ( var li_SizeRead, li_BytesTotal : Longint ) : Boolean ;
var li_pos, li_i : Longint ;
Begin
Result := inherited BeforeCopyBuffer ( li_SizeRead, li_BytesTotal );
if FExcludeReading
and ( FExcludeStart <> '' )
and ( FExcludeEnd <> '' )
Then
Begin
li_pos := 0 ;
li_i := 0 ;
while li_pos < li_SizeRead do
if lb_ExcludedFound then
Begin
End
Else
Begin
End;
end;
End ;
procedure TExtFilePartialCopy.AfterCopyBuffer ;
Begin
End ;
function TExtFilePartialCopy.BeforeCopy : Boolean ;
Begin
Result := inherited BeforeCopy ();
if FExcludeReading
and ( FExcludeStart <> '' )
and ( FExcludeEnd <> '' )
Then
Begin
// lpch_excludeStart := fs_HexToString ( FExcludeStart );
// lpch_excludeEnd := fs_HexToString ( FExcludeEnd );
End ;
End ;
procedure Register;
begin
RegisterComponents('Extended', [TExtFileCopy]);
end;
initialization
{$i U_ExtFileCopy.lrs}
end.