unit FmxUtils; interface uses SysUtils, Windows, Classes, Consts; type EInvalidDest = class(EStreamError); EFCantMove = class(EStreamError); procedure CopyFile(const FileName, DestName: string); procedure MoveFile(const FileName, DestName: string); function GetFileSize(const FileName: string): LongInt; function FileDateTime(const FileName: string): TDateTime; function HasAttr(const FileName: string; Attr: Word): Boolean; function ExecuteFile(const FileName, Params, DefaultDir: string): THandle; implementation uses Forms, ShellAPI; const SInvalidDest = 'Destination %s does not exist'; SFCantMove = 'Cannot move file %s'; procedure CopyFile(const FileName, DestName: string); var CopyBuffer: Pointer; { buffer for copying } BytesCopied: Longint; Source, Dest : Integer; { handles } Len : Integer; Destination: TFileName; { holder for expanded destination name } const ChunkSize : Longint = 8192; { copy in 8K chunks } begin Destination := ExpandFileName(DestName); { expand the destination path } if HasAttr(Destination, faDirectory) then { if destination is a directory... } begin Len := Length(Destination); if Destination[Len] = '\' then Destination := Destination + ExtractFileName(FileName) { ...clone file name } else Destination := Destination + '\' + ExtractFileName(FileName); { ...clone file name } end; GetMem(CopyBuffer, ChunkSize); { allocate the buffer } try Source := FileOpen(FileName, fmShareDenyWrite); { open source file } if Source < 0 then raise EFOpenError.CreateFmt('File open Error', [FileName]); try Dest := FileCreate(Destination); { create output file; overwrite existing } if Dest < 0 then raise EFCreateError.CreateFmt('File creation error', [Destination]); try repeat BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk } if BytesCopied > 0 then { if we read anything... } FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk } until BytesCopied < ChunkSize; { until we run out of chunks } finally FileClose(Dest); { close the destination file } end; finally FileClose(Source); { close the source file } end; finally FreeMem(CopyBuffer, ChunkSize); { free the buffer } end; end; { MoveFile procedure } { Moves the file passed in FileName to the directory specified in DestDir. Tries to just rename the file. If that fails, try to copy the file and delete the original. Raises an exception if the source file is read-only, and therefore cannot be deleted/moved. } procedure MoveFile(const FileName, DestName: string); var Destination: string; begin Destination := ExpandFileName(DestName); { expand the destination path } if not RenameFile(FileName, Destination) then { try just renaming } begin if HasAttr(FileName, faReadOnly) then { if it's read-only... } raise EFCantMove.Create(Format(SFCantMove, [FileName])); { we wouldn't be able to delete it } CopyFile(FileName, Destination); { copy it over to destination...} // DeleteFile(FileName); { ...and delete the original } end; end; { GetFileSize function } { Returns the size of the named file without opening the file. If the file doesn't exist, returns -1. } function GetFileSize(const FileName: string): LongInt; var SearchRec : TSearchRec; begin try if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then Result := SearchRec.Size else Result := -1; finally SysUtils.FindClose(SearchRec); end; end; function FileDateTime(const FileName: string): System.TDateTime; begin Result := FileDateToDateTime(FileAge(FileName)); end; function HasAttr(const FileName: string; Attr: Word): Boolean; var FileAttr : Integer; begin FileAttr := FileGetAttr(FileName); if FileAttr = -1 then FileAttr := 0; Result := (FileAttr and Attr) = Attr; end; function ExecuteFile(const FileName, Params, DefaultDir: string): THandle; begin Result := ShellExecute(Application.MainForm.Handle, nil, PChar(FileName), PChar(Params), PChar(DefaultDir), SW_SHOW); end; end.