有没有人研究 文件拷贝....
使用delphi的函数拷贝似乎比fastcopy慢很多呀,使用线程更慢,不知道各位有什么好方法呢....
unit ReadWriteUnits;
{
拷贝文件
}
interface
uses
Windows,Classes,SysUtils,Messages,CopyHintUnits,Forms;
const WM_COPYEND_MSG = WM_USER + 1024;
type
pByte=array of byte;
pReadWriteInFo=^TReadWriteInfo;
TReadWriteInfo=record
ParentID:int64; //回送消息的父类句柄
Data:LongWord; //数据指针
Start:LongWord; //开始位置
len:LongWord; //拷贝数据长度
end;
TReadWriteFile = class(TThread)
private
{ Private declarations }
DataFile,DescF: HFile;
FWND:HWND;
FShowProgress:boolean;
FReadSum:int64;
Buf1,Buf2: array of byte;
FReadf,FWriteF:string;//读写的文件名称
pForm:TCopyHintForm;
iFileLength:int64; //文件的长度
ReadNumber,WriteNumber: LongWord;
ToReadLength:LongWord;
BuffFlag:boolean; //缓冲区标志,false使用buf1,true使用Buf2
ReadthreadCount:integer;
finfo1,finfo2:TReadWriteInfo;
Address1,address2:LongWord;
writethread1,writethread2:Tthread;
Handles:TWOHandleArray;
IsWritethread:boolean;
protected
procedure Execute; override;
procedure Openf;
procedure CLosef;
function CopyFile:boolean;
procedure ShowProgress;
procedure ResumWrite1;
procedure ResumWrite2;
procedure ExitPro;
public
constructor Create(MsgParent:HWND;const ReadFile,WriteFile:String;ShowProgress:boolean);
destructor Destroy;
end;
TWritethread=class(TThread)
private
Buf: pByte;
FDataFile:HFile;
FInfo:TReadWriteInfo;
protected
procedure Execute; override;
procedure WriteData;
procedure PostCopyEnd;
public
constructor Create(f:HFile;Info:TReadWriteInfo); //写文件的句柄和数据源结构
end;
implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TReadWriteFile.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
constructor TWritethread.Create(f:HFile;Info:TReadWriteInfo); //写文件的句柄和数据源结构
begin
inherited Create(false);
FreeOnTerminate:=true;
FDataFile:=f;
FInfo:=Info;
end;
procedure TWritethread.Execute;
var
msg:TMSG;
begin
WriteData;
while (not Terminated) and GetMessage(msg,0,0,0) do //
begin
if msg.message=WM_USER then
begin
FInfo:=pReadWriteInFo(msg.wParam)^;
WriteData;
end;
//响应外部消息
TranslateMessage(msg);
DispatchMessage(msg);
end;
end;
procedure TWritethread.PostCopyEnd;
begin
//一次数据写完毕,返回消息
PostThreadMessage(FInfo.ParentID,WM_COPYEND_MSG,integer(@FInfo),integer(@Buf[0]));
end;
procedure TWritethread.WriteData;
var
WriteNumber:LongWord;
begin
Buf:=pByte(FInfo.data);
//设定写数据的位置
SetFilePointer(FDataFile,FInfo.Start, nil, FILE_BEGIN);
//存储流到文件
WriteFile(FDataFile,Buf[0], FInfo.len,WriteNumber,nil);
PostCopyEnd;
end;
{ TReadWriteFile }
constructor TReadWriteFile.Create(MsgParent:HWND;const ReadFile,WriteFile:String;ShowProgress:boolean);
begin
inherited Create(false);
FreeOnTerminate:=true;
FReadf:= ReadFile;
FWriteF:=WriteFile;
FShowProgress:=ShowProgress;
FWND:=MsgParent;
BuffFlag:=false;
pForm:=nil;
end;
destructor TReadWriteFile.Destroy;
begin
end;
procedure TReadWriteFile.CLosef;
begin
try
setlength(Buf1, 0);
setlength(Buf2, 0);
CloseHandle(DescF);
CloseHandle(DataFile);
if pForm <>nil then pForm.Free;
finally
if not self.Terminated then
PostMessage(FWND,WM_COPYEND_MSG,0,0);
end;
end;
procedure TReadWriteFile.Openf;
var
i,FHandle:integer;
begin
//获取源文件的长度
if not fileexists(FReadf) then
begin
exit;
end;
//打开文件源
DataFile := CreateFile(PChar(FReadf), GENERIC_READ,
0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if DataFile = 0 then
begin
exit;
end;
iFileLength := GetFileSize(DataFile, nil);
SetFilePointer(DataFile, 0, nil, FILE_BEGIN); //移动到文件开始
//创建需要存储的文件
DescF := CreateFile(PChar(FWriteF), GENERIC_WRITE,
0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if DataFile = 0 then
begin
exit;
end;
//设定文件的长度
setfilepointer(DescF,iFileLength,nil,file_begin);
setendoffile(DescF);
SetFilePointer(DescF, 0, nil, FILE_BEGIN);
//(因为正常情况下,磁盘重复读取会导致很慢,所以这里只是开一个线程去读取文件)
FReadSum:=0;
ToReadLength:=10*1024*1024; //每次读取缓冲大小 //20m的缓冲区
setlength(Buf1,ToReadLength+1);
setlength(Buf2,ToReadLength+1);
if IsWritethread then
begin
finfo1.ParentID:=self.ThreadID;
finfo1.Data:=LongInt(@Buf1[0]);
finfo1.Start:=0;
finfo1.len:=0;
finfo2.ParentID:=self.ThreadID;
finfo2.Data:=LongInt(@Buf2[0]);
finfo2.Start:=0;
finfo2.len:=0;
Address1:= finfo1.Data;
Address2:= finfo2.Data;
for i:=0 to 1 do //复制数据到缓冲区
begin
if not CopyFile then break;
end;
//启动写数据线程
writethread1:=TWritethread.Create(DescF,finfo1);
writethread2:=TWritethread.Create(DescF,finfo2);
Handles[0]:=writethread1.Handle;
Handles[1]:=writethread2.Handle;
Sleep(100);
end else
begin
pForm:=TCopyHintForm.Create(Application);
pForm.ProgressBar1.Max:= iFileLength;
pForm.ProgressBar1.Position:=0;
while FReadSum < iFileLength do
begin
//读取数据
ReadFile(DataFile, Buf1[0], ToReadLength, ReadNumber, nil);
//重新确定一下读取的文件大小
FReadSum:=FReadSum + ReadNumber; //ReadNumber --为每次实际读取的文件大小
//存储流到文件
WriteFile(DescF, Buf1[0], ReadNumber, WriteNumber, nil);
ShowProgress;
if self.Terminated then break;
end;
pForm.Free;
pForm:=nil;
end;
end;
procedure TReadWriteFile.ShowProgress;
begin
if FShowProgress then
begin
pForm.ProgressBar1.Position:=FReadSum;
pForm.Show;
Application.ProcessMessages;
end;
end;
function TReadWriteFile.CopyFile:boolean;
begin
Result:=false;
//读取数据
if FReadSum < iFileLength then
begin
if BuffFlag then
begin
ReadFile(DataFile, Buf1[0], ToReadLength, ReadNumber, nil);
finfo1.Start:=FReadSum;
finfo1.len:=ReadNumber;
end else
begin
ReadFile(DataFile, Buf2[0], ToReadLength, ReadNumber, nil);
finfo2.Start:=FReadSum;
finfo2.len:=ReadNumber;
end;
//重新确定一下读取的文件大小
FReadSum:=FReadSum + ReadNumber; //ReadNumber --为每次实际读取的文件大小
//重新修改标志
BuffFlag:=not BuffFlag;
Result:=true;
end else
begin
Synchronize(ExitPro);
end;
end;
procedure TReadWriteFile.ExitPro;
begin
PostThreadMessage(self.ThreadID,WM_QUIT,0,0);
end;
procedure TReadWriteFile.ResumWrite1;
begin
PostThreadMessage(writethread1.ThreadID,WM_USER,integer(@finfo1),0);
end;
procedure TReadWriteFile.ResumWrite2;
begin
PostThreadMessage(writethread2.ThreadID,WM_USER,integer(@finfo2),0);
end;
procedure TReadWriteFile.Execute;
var
msg:TMSG;
tmpinfo:TReadWriteInfo;
begin
IsWritethread:=false; //测试标准,是否使用子线程写数据
if IsWritethread then //180m 耗时7s
begin
Openf; //打开和创建文件
while (not Terminated) and GetMessage(msg,0,0,0) do //
begin
if msg.message=WM_COPYEND_MSG then
begin
if msg.lParam = Address1 then
begin
BuffFlag:=true;
if CopyFile then
//重新激活复制子线程
ResumWrite1;
end else if msg.lParam = Address2 then
begin
BuffFlag:=false;
if CopyFile then
ResumWrite2;
end;
end;
//响应外部消息
TranslateMessage(msg);
DispatchMessage(msg);
end;
//等待线程结束
WaitForMultipleObjects(3, @Handles, True, INFINITE);
end else //单独读写过程 180m耗时 5s
Synchronize(Openf);
//关闭文件
Synchronize(CLosef);
end;
end.