求大于2G的文件COPY代码,带进程条 需要一个大于2G的带进度度的文件显示COPY代码,不希望用COPYFILE。。求救!!!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Function CopyProgressRoutine( TotalFileSize : Int64; TotalBytesTransferred : Int64; StreamSize : Int64; StreamBytesTransferred : Int64; dwStreamNumber : Cardinal; dwCallbackReason : DWord; hSourceFile : THandle; hDestinationFile : THandle; lpData : Pointer):integer;Begin form1.ProgressBar1.Max:=StreamSize; form1.ProgressBar1.Min :=0; form1.ProgressBar1.Position := StreamBytesTransferred; application.ProcessMessages ; Result := PROGRESS_CONTINUE;end;{if copyfileex(PChar(edt1.Text),PChar(edt2.text), @copyprogressroutine, nil, 0, COPY_FILE_FAIL_IF_EXISTS) thenbeginshowmessage( 'COPY Success ');pb1.position:=0;end;} if copyfileex(PChar(edt1.Text),PChar(edt2.text), //调用函数 @copyprogressroutine, nil, 0, COPY_FILE_FAIL_IF_EXISTS) thenbeginshowmessage( 'COPY Success ');pb1.position:=0;end; 不想用copyfileEX 这个代码效率有点低,是我现在用的,就是因为这个才求助的。。 如果单个大文件,copyfile应该也是最高效的了吧除非是需要复制到网络共享?压缩高的话,可以先压缩、复制、再解压缩 COPYFILE的效率是不错,但COPYFILEEX就不怎么样了,因为回调原因。。但因为文件太大,一般都大于2G所以,不给个提示还不行。。 俺感觉得这还不如copyfileex呢。如果是多个用户在copy,用copyifile传输怎么样效率都高不了,而如果是单独为某一个用户提供copy,那copyfileex的回调效率怎么也低不到能让用户察觉的程度。 系统应用是从服务器copy数据到本地,我最开始是用TfileStream,使用速度与效率都十分理想,但发现当文件超过2GB的时候有错误,于是用copyfile速度当然很快,但没有指示,后来就用copyfileEx,但这个效率有点低! 不用每次都在回调中刷新界面的.到达一定字节才刷新一次,这样就可以大大提高速度了.Type PCFPRData = ^TCFPRData; TCFPRData = record PB : TProgressBar; Max : Integer; //之所以不直接用TProgressBar来比较,看一下TProgressBar.GetMax就知道了 Position : Integer; //同上 end;var bUserCancel : Boolean;Function CopyFilePR(TotalFileSize,TotalBytesTransferred,StreamSize,StreamBytesTransferred:Int64; dwStreamNumber , dwCallbackReason : Cardinal; hSourceFile , hDestinationFile : THandle; Data : PCFPRData):DWORD; stdcall;var iPosition : integer;begin //40M以下的文件就不用显示进度条了,这里假设了复制速度在40M/秒以上,龟速复制不适合本回调 if StreamSize<40*1024*1024 then begin Result := PROGRESS_QUIET; Exit; end; Result := PROGRESS_CONTINUE; if Data.Max=0 then begin //只设置一次Max Data.Max := StreamSize DIV (6*1024*1024); //48M/秒的复制速度,每秒跳动8次左右 Data.PB.Max := Data.Max; end; iPosition := StreamBytesTransferred DIV (6*1024*1024); if iPosition<>Data.Position then begin //当需要同步进度条的时候才同步 Data.Position := iPosition; Data.PB.Position := iPosition; Application.ProcessMessages; //这里响应取消复制的操作 if bUserCancel then Result := PROGRESS_CANCEL; //取消文件复制,并删除目标文件 end;end;procedure TForm1.CancelBtnClick(Sender: TObject);begin bUserCancel := True;end;procedure TForm1.Button1Click(Sender: TObject);var CFPRData : TCFPRData;begin DeleteFile('F:\DD.MKV'); FillChar(CFPRData , SizeOf(CFPRData) , 0); CFPRData.PB := ProgressBar1; ProgressBar1.Tag := 0; ProgressBar1.Position := 0; bUserCancel := False; CopyFileEx('F:\多媒体\电影收藏\黑衣人3\Men.in.Black.3.2012.720p.BluRay.x264.DTS-HDChina.mkv' , 'F:\DD.MKV' , @CopyFilePR , @CFPRData , NIL , COPY_FILE_FAIL_IF_EXISTS);end;这个文件是6G,比直接CopyFile只慢一点点. 感谢kiboisme,测试了你的代码,工作正常,效率要比以前有所提高!!!可能是因为我的是局域网环境,所以速度也不是太理想!千兆局域网环境!手头有个函数,这个速度就比较理想,但遗憾的是不支持大于2G。。能否帮忙改改?思路可能是要进行文件分隔与定位。function FileCopy(SourceFile,TargetFile : string;ProgressBar :TProgressBar ) : boolean;var getStream,setStream: TFileStream; num, n: Int; buf: PByte; BufSize,block: Integer;begin result := false; getStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareCompat); setStream := TFileStream.Create(TargetFile, fmCreate); num := getStream.Size; setStream.Size := num; getStream.Position := 0; setStream.Position := 0; BufSize := num; block := BufSize div 100; GetMem(buf, BufSize); ProgressBar.Max := 100; ProgressBar.Position := 0; while num <> 0 do begin Application.ProcessMessages; n := block; if n > num then n := num; getStream.ReadBuffer(buf^, n); setStream.WriteBuffer(buf^, n); ProgressBar.Position := Trunc((1 - num / BufSize)*100); Dec(num, n); end; ProgressBar.Position := 0; FreeMem(buf, BufSize); getStream.Free; setStream.Free; result := true;end; BufSize,block: Integer;begin getStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareCompat); num := getStream.Size; //这里获取文件大小,TStream.Size是一个64位整数,把它赋给以个32位的整数,它的高位自然就被抹杀了,所以超过2G的文件就会出错. BufSize := num; GetMem(buf, BufSize); //直接申请文件大小的内存,如果是大文件(比如1,2或者3G),那你这程序不是要申请1,2或者3G的内存? 如果要改改动的地方有点多。 n := block; getStream.ReadBuffer(buf^, n); 从这里看,只使用了block字节的内存,block=文件大小/100,却提交了文件大小字节的内存,估计应该是block字节的大小, 变量的区域问题 image控件如何显示memorystream 从idhttp中get的图象?? 圣诞节快乐 ,下班后跟女朋友看<功夫>哈哈 散100分 ,什么?太小气!不回吧.......... 简单的问题快来接分哦! 急死人的问题,曾经从未碰过 ImageEnMview控制tif文件的大小和清晰度 序列号 ADO的使用 如何实现服务器和本地机传送文件?就像oicq一样! 我初学我要求师谁能愿意受我一拜! 新手求教,如何在DBGrid插入首行,进行前期汇总。然后再总结。 如何用delphi7编写温度云图?
Function CopyProgressRoutine(
TotalFileSize : Int64;
TotalBytesTransferred : Int64;
StreamSize : Int64;
StreamBytesTransferred : Int64;
dwStreamNumber : Cardinal;
dwCallbackReason : DWord;
hSourceFile : THandle;
hDestinationFile : THandle;
lpData : Pointer):integer;Begin
form1.ProgressBar1.Max:=StreamSize;
form1.ProgressBar1.Min :=0;
form1.ProgressBar1.Position := StreamBytesTransferred;
application.ProcessMessages ;
Result := PROGRESS_CONTINUE;
end;{if copyfileex(PChar(edt1.Text),PChar(edt2.text),
@copyprogressroutine,
nil,
0,
COPY_FILE_FAIL_IF_EXISTS) then
begin
showmessage( 'COPY Success ');
pb1.position:=0;
end;
}
@copyprogressroutine,
nil,
0,
COPY_FILE_FAIL_IF_EXISTS) then
begin
showmessage( 'COPY Success ');
pb1.position:=0;
end;
如果是多个用户在copy,用copyifile传输怎么样效率都高不了,而如果是单独为某一个用户提供copy,那copyfileex的回调效率怎么也低不到能让用户察觉的程度。
Type
PCFPRData = ^TCFPRData;
TCFPRData = record
PB : TProgressBar;
Max : Integer; //之所以不直接用TProgressBar来比较,看一下TProgressBar.GetMax就知道了
Position : Integer; //同上
end;var
bUserCancel : Boolean;Function CopyFilePR(TotalFileSize,TotalBytesTransferred,StreamSize,StreamBytesTransferred:Int64;
dwStreamNumber , dwCallbackReason : Cardinal;
hSourceFile , hDestinationFile : THandle;
Data : PCFPRData):DWORD; stdcall;
var
iPosition : integer;
begin
//40M以下的文件就不用显示进度条了,这里假设了复制速度在40M/秒以上,龟速复制不适合本回调
if StreamSize<40*1024*1024 then begin
Result := PROGRESS_QUIET;
Exit;
end;
Result := PROGRESS_CONTINUE; if Data.Max=0 then begin //只设置一次Max
Data.Max := StreamSize DIV (6*1024*1024); //48M/秒的复制速度,每秒跳动8次左右
Data.PB.Max := Data.Max;
end;
iPosition := StreamBytesTransferred DIV (6*1024*1024);
if iPosition<>Data.Position then begin //当需要同步进度条的时候才同步
Data.Position := iPosition;
Data.PB.Position := iPosition;
Application.ProcessMessages;
//这里响应取消复制的操作
if bUserCancel then Result := PROGRESS_CANCEL; //取消文件复制,并删除目标文件
end;
end;procedure TForm1.CancelBtnClick(Sender: TObject);
begin
bUserCancel := True;
end;procedure TForm1.Button1Click(Sender: TObject);
var
CFPRData : TCFPRData;
begin
DeleteFile('F:\DD.MKV'); FillChar(CFPRData , SizeOf(CFPRData) , 0);
CFPRData.PB := ProgressBar1;
ProgressBar1.Tag := 0;
ProgressBar1.Position := 0;
bUserCancel := False;
CopyFileEx('F:\多媒体\电影收藏\黑衣人3\Men.in.Black.3.2012.720p.BluRay.x264.DTS-HDChina.mkv' ,
'F:\DD.MKV' , @CopyFilePR , @CFPRData , NIL , COPY_FILE_FAIL_IF_EXISTS);
end;这个文件是6G,比直接CopyFile只慢一点点.
可能是因为我的是局域网环境,所以速度也不是太理想!千兆局域网环境!
手头有个函数,这个速度就比较理想,但遗憾的是不支持大于2G。。能否帮忙改改?
思路可能是要进行文件分隔与定位。function FileCopy(SourceFile,TargetFile : string;ProgressBar :TProgressBar ) : boolean;
var
getStream,setStream: TFileStream;
num, n: Int;
buf: PByte;
BufSize,block: Integer;
begin
result := false;
getStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareCompat);
setStream := TFileStream.Create(TargetFile, fmCreate); num := getStream.Size;
setStream.Size := num;
getStream.Position := 0;
setStream.Position := 0; BufSize := num;
block := BufSize div 100;
GetMem(buf, BufSize); ProgressBar.Max := 100;
ProgressBar.Position := 0;
while num <> 0 do
begin
Application.ProcessMessages;
n := block;
if n > num then n := num;
getStream.ReadBuffer(buf^, n);
setStream.WriteBuffer(buf^, n);
ProgressBar.Position := Trunc((1 - num / BufSize)*100);
Dec(num, n);
end;
ProgressBar.Position := 0;
FreeMem(buf, BufSize);
getStream.Free;
setStream.Free;
result := true;
end;
begin
getStream := TFileStream.Create(SourceFile, fmOpenRead or fmShareCompat);
num := getStream.Size; //这里获取文件大小,TStream.Size是一个64位整数,把它赋给以个32位的整数,它的高位自然就被抹杀了,所以超过2G的文件就会出错. BufSize := num;
GetMem(buf, BufSize); //直接申请文件大小的内存,如果是大文件(比如1,2或者3G),那你这程序不是要申请1,2或者3G的内存? 如果要改改动的地方有点多。
n := block;
getStream.ReadBuffer(buf^, n);
从这里看,只使用了block字节的内存,block=文件大小/100,
却提交了文件大小字节的内存,估计应该是block字节的大小,