使用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.

解决方案 »

  1.   

    有没有使用win32 api copyfile试试。
    createfile建立新文件的时候可以设置为不缓冲直接写,具体可以参考createfile的参数说明。
      

  2.   

    CopyFile  拷贝大文件容易出现假死机情况,拷贝上边相同文件 耗时8s左右.. 而fastcopy 工具耗时大概4s.不到..,,...
      

  3.   

    xcopy  /J           复制时不使用缓冲的 I/O。推荐复制大文件时使用。
      

  4.   

    弄了大半天 。。还是CopyFile 速度最快,瞧了瞧,fastcopy的源码,似乎是用copymemory...但是我调用它,速度还是跟不上...糊涂了
      

  5.   

    自己去写文件纯属自找麻烦。
    windows提供两个API:
    CopyFile,
    CopyFileEx
    后者可以反馈实时进度。难道自写的有微软谢的快?
      

  6.   

    话说,网上的fastcopy工具,速度比微软的 拷贝快了 N 多,.
      

  7.   

    最为明显的,N多目录,文件同时拷贝时速度更快 ...fastcopy拷贝信息...TotalRead = 184.1 MB
    TotalWrite = 184.1 MB
    TotalFiles = 2 (0)
    TotalTime= 4.25 sec
    TransRate= 43.32 MB/s
    FileRate  = 0.47 files/s
      

  8.   

    TransRate= 43.32 MB/s
    这个速度已经达到你硬盘速度极限的多少? 60%?
      

  9.   

    我这个是7200转的硬盘,理论上可以达到60m以上吧.....所以 fastcopy的拷贝速度应该有80%以上了。但是实际上,使用api拷贝,速度很低,所以 有些晕咧...