使用delphi的函数拷贝似乎比fastcopy慢很多呀,使用线程更慢,不知道各位有什么好方法呢....unit ReadWriteUnits;{
拷贝文件
}interfaceuses
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;
beginend;
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.
拷贝文件
}interfaceuses
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;
beginend;
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.
解决方案 »
- 如何用createDocumentFromUrl打开一个文档?
- 请问 如何 实现 像 "财富快车" 的 "PopUpedit" 的 功能(带 图片 ) 急!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- 怎样同时查询两个Access数据库?
- 在delphi中如何实现远程锁定计算机,锁定键盘等
- ADO问题
- ***急,如何将Excel文件导入到SqlServer表中??***
- 软件开发难题(高分)
- 对2009qq的用户发临时会话,怎么样能实现让其接受。
- 得到一个按钮句柄后,如何得到这个按钮的状态
- 在delphi中如何实现条形码的生成
- access 长时间 字段 的创建
- 定制程序需要多少钱
createfile建立新文件的时候可以设置为不缓冲直接写,具体可以参考createfile的参数说明。
windows提供两个API:
CopyFile,
CopyFileEx
后者可以反馈实时进度。难道自写的有微软谢的快?
TotalWrite = 184.1 MB
TotalFiles = 2 (0)
TotalTime= 4.25 sec
TransRate= 43.32 MB/s
FileRate = 0.47 files/s
这个速度已经达到你硬盘速度极限的多少? 60%?