读书人

求大于2G的资料COPY代码带进程条

发布时间: 2013-03-10 09:38:39 作者: rapoo

求大于2G的文件COPY代码,带进程条
需要一个大于2G的带进度度的文件显示COPY代码,不希望用COPYFILE。。
求救!!!!!
[解决办法]


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;
}

[解决办法]
引用:
COPYFILE的效率是不错,但COPYFILEEX就不怎么样了,因为回调原因。。但因为文件太大,一般都大于2G所以,不给个提示还不行。。

不用每次都在回调中刷新界面的.到达一定字节才刷新一次,这样就可以大大提高速度了.
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只慢一点点.
[解决办法]
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字节的大小,

读书人网 >.NET

热点推荐