首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

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

2013-03-10 
求大于2G的文件COPY代码,带进程条需要一个大于2G的带进度度的文件显示COPY代码,不希望用COPYFILE。。求救!!!

求大于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字节的大小,

热点排行