求大于2G的文件COPY代码,带进程条

gaoz 2013-02-27 07:48:03
需要一个大于2G的带进度度的文件显示COPY代码,不希望用COPYFILE。。
求救!!!!!
...全文
709 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
gaoz 2013-03-07
  • 打赏
  • 举报
回复
谢谢各位了,特别是kiboisme!!
蓝色光芒 2013-03-06
  • 打赏
  • 举报
回复
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字节的大小,
gaoz 2013-03-05
  • 打赏
  • 举报
回复
顶下!!@@@@
gaoz 2013-03-03
  • 打赏
  • 举报
回复
感谢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;
蓝色光芒 2013-03-01
  • 打赏
  • 举报
回复
引用 5 楼 gaoz 的回复:
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只慢一点点.
gaoz 2013-03-01
  • 打赏
  • 举报
回复
系统应用是从服务器copy数据到本地,我最开始是用TfileStream,使用速度与效率都十分理想,但发现当文件超过2GB的时候有错误,于是用copyfile速度当然很快,但没有指示,后来就用copyfileEx,但这个效率有点低!
JPEXE 2013-03-01
  • 打赏
  • 举报
回复
来学习一下#10的代码
Henry.6 2013-03-01
  • 打赏
  • 举报
回复
study study
sololie 2013-02-28
  • 打赏
  • 举报
回复
引用
看看拷贝过程中,目标文件的大小会不会准确增加 如果是,可以开一个线程定时检测结果文件的大小,更新界面报告最新进度
俺感觉得这还不如copyfileex呢。 如果是多个用户在copy,用copyifile传输怎么样效率都高不了,而如果是单独为某一个用户提供copy,那copyfileex的回调效率怎么也低不到能让用户察觉的程度。
萨弗迪发个 2013-02-28
  • 打赏
  • 举报
回复
http://supercopier.sfxteam.org/
haitao 2013-02-28
  • 打赏
  • 举报
回复
引用 5 楼 gaoz 的回复:
COPYFILE的效率是不错,但COPYFILEEX就不怎么样了,因为回调原因。。但因为文件太大,一般都大于2G所以,不给个提示还不行。。
看看拷贝过程中,目标文件的大小会不会准确增加 如果是,可以开一个线程定时检测结果文件的大小,更新界面报告最新进度
gaoz 2013-02-28
  • 打赏
  • 举报
回复
COPYFILE的效率是不错,但COPYFILEEX就不怎么样了,因为回调原因。。但因为文件太大,一般都大于2G所以,不给个提示还不行。。
haitao 2013-02-28
  • 打赏
  • 举报
回复
如果单个大文件,copyfile应该也是最高效的了吧 除非是需要复制到网络共享?压缩高的话,可以先压缩、复制、再解压缩
gaoz 2013-02-28
  • 打赏
  • 举报
回复
不想用copyfileEX 这个代码效率有点低,是我现在用的,就是因为这个才求助的。。
seagull327 2013-02-27
  • 打赏
  • 举报
回复
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;
seagull327 2013-02-27
  • 打赏
  • 举报
回复

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

16,743

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧