shfileoperation和copyfileex文件操作

时间:2024-02-18 22:00:01
shfileoperation和copyfileex都可用于对文件的拷贝、剪切、删除等操作
区别一:shfileoperation可以对文件夹和文件都可以直接进行操作,而copyfileex只能对文件进行操作,如果想拷贝文件夹,要自己去遍历文件夹的文件,然后一个个的操作。
区别二:当拷贝文件时,shfileoperation的目标路径为不包括文件的路径, copyfileex的目标路径为包括拷贝文件名的路径。例如 拷贝c盘中的1.txt文件到C盘中的aa文件夹中 shfileoperation为"c:\1.txt"->"c:\aa\"     
copyfileex"c:\1.txt"->"c:\aa\1.txt"
区别三:copyfileex有回调函数,可以获得拷贝文件的各种信息。
 
总体来说,shfileoperation比copyfileex要方便使用一些,但是对于拷贝的文件的信息情况不是很明确。
shfileoperation介绍
以下来自百度:
SHFileOperation是一种外壳函数,用它可以实现各种文件操作,如文件的拷贝、删除、移动等,该函数使用起来非常简单,它只有一个指向SHFILEOPSTRUCT结构的参数。使用SHFileOperation()函数时只要填写该专用结构--SHFILEOPSTRUCT,告诉Windows执行什么样的操作,以及其它重要信息就行了。SHFileOperation()的特别之处在于它是一个高级外壳函数,不同于低级文件处理。当调用SHFileOperation操作文件时,相应的外壳拷贝处理器(如果有的话)被调用。
 
函数原型:
int SHFileOperation( _Inout_ LPSHFILEOPSTRUCT lpFileOp);
需要的库文件:
#include <Shlwapi.h>
#pragma comment (lib,"Shlwapi.lib")
参数
lpFileOp : 一个指向SHFILEOPSTRUCT结构的指针
返回值:
返回0成功,
SHFILEOPSTRUCT结构说明
typedef struct _SHFILEOPSTRUCT {
HWND hwnd;
UINT wFunc;
PCZZTSTR pFrom;
PCZZTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
PCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

  hwnd; //父窗口句柄, 0为桌面
wFunc; 功能标识
FO_COPY 复制
FO_DELETE 删除
FO_MOVE 移动
FO_RENAME 重命名
pFrom 源文件或者源文件夹,(source file)
pTo 目的文件或文件夹 (destination)
fFlags 控制文件的标志位
FOF_ALLOWUNDO 准许撤销
FOF_CONFIRMMOUSE 没有被使用,,,
FOF_FILESONLY
通配符的文件名( *.* )只对文件(不是文件夹)进行操作。
FOF_MULTIDESTFILES
The pTo member specifies multiple destination files (one for each source file in pFrom)
rather than one directory where all source files are to be deposited.
(不知道怎么翻译过来,大家体验一下精髓)
FOF_NOCONFIRMATION 不出现任何对话框
FOF_NOCONFIRMMKDIR 创建文件夹的时候不用确认
FOF_NO_CONNECTED_ELEMENTS
Version 5.0适用,,不移动连接文件(connected files),只移动特定文件
FOF_NOCOPYSECURITYATTRIBS
Version 4.71适用,,复制移动文件的时候不复制安全属性,而是为文件指定新的安全属性
FOF_NOERRORUI 如果发生错误, 不要 显示对话框给用户
FOF_NORECURSEREPARSE 没有被使用
FOF_NORECURSION 不递归目录
FOF_NO_UI
Windows Vista中,默默的进行操作,不给用户呈现任何UI。
这相当于FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI
|FOF_NOCONFIRMMKDIR 。
FOF_RENAMEONCOLLISION 移动复制的时候如果名字重名,自动分配新名字
FOF_SILENT 不显示进度条提示框
FOF_SIMPLEPROGRESS 显示一个进度条,但不显示单个文件名,
FOF_WANTMAPPINGHANDLE
如果指定了FOF_RENAMEONCOLLISION,说明此时是在重命名,
分配一个名称映射对象,其中包含他们的旧的和新的名字到hNameMappings成员。
如果不再使用,需要用SHFreeNameMappings释放。
FOF_WANTNUKEWARNING
当一个文件被永久删除的时候,弹出警告框
 
copyfileex介绍
 

{ 回调函数原型 }
 
  TFarProc = Pointer;
  TFNProgressRoutine = TFarProc;                //指针类型
 
  function CopyProgress(
    TotalFileSize         : LARGE_INTEGER;      // 文件总大小,字节
    TotalBytesTransferred : LARGE_INTEGER;      // 已复制的文件大小,字节
    StreamSize            : LARGE_INTEGER;      // 当前流的总字节数
    StreamBytesTransferred: LARGE_INTEGER;      // 当前流已拷贝的字节数
    dwStreamNumber        : DWORD;              // 当前流序号
    dwCallbackReason      : DWORD;              // 回调函数的状态,见定义
    hSourceFile           : THANDLE;            // 来源文件句柄
    hDestinationFile      : THANDLE;            // 目标文件句柄
    lpData                : Pointer             // CopyFileEx 函数传递过来的参数
    ) : DWORD; stdcall;                         // 回调函数的返回值,见定义
 
 
 
{ 说明 }
 
    该函数复制一个已存在的文件到一个新文件。该函数保留了文件的扩展属性,OLE存储格式和文件属性。文件的安全属性不复制到新文件中去。
    如果目标文件存在,且具有只读属性,则函数执行失败。
    该函数每复制 65536字节(即64KB) 的内容后就调用一次回调函数。
    第一次调用回调函数时 dwCallbackReason(回调函数的状态) 的值为 CALLBACK_STREAM_SWITCH,此时不复制任何数据,只是告诉回调函数,将要开始复制数据了。
    此函数是线程同步的,也就是说,在主窗口中调用此函数时,窗口将无法响应用户的操作,直到文件复制完毕为止。
    此函数无法复制锁定的文件,比如页面文件 PageFile.sys。就像在资源管理器中复制 PageFile.sys 一样,会提示文件正被另一个程序使用,无法复制。此函数不会提示错误,只会返回逻辑值否,表示复制失败。
 
 
 
{============================================================}
{  例子                                                      }
{============================================================}
 
unit Main;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  TForm2 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form2             : TForm2;
  Cancel            : Boolean;
  iCount            : Integer;
 
implementation
 
{$R *.dfm}
 
function CopyProgress(
  TotalFileSize: LARGE_INTEGER;                   // 文件总大小,字节
  TotalBytesTransferred: LARGE_INTEGER;           // 已复制的文件大小,字节
  StreamSize: LARGE_INTEGER;                      // 当前流的总字节数
  StreamBytesTransferred: LARGE_INTEGER;          // 当前流已拷贝的字节数
  dwStreamNumber: DWORD;                          // 当前流序号
  dwCallbackReason: DWORD;                        // 回调函数的状态,见定义
  hSourceFile: THANDLE;                           // 来源文件句柄
  hDestinationFile: THANDLE;                      // 目标文件句柄
  lpData: Pointer                                 // CopyFileEx 函数传递过来的参数
  ): DWORD; stdcall;                              // 回调函数的返回值,见定义
begin
  // if iCount = 2 then begin
  //   Result := PROGRESS_STOP;
  //   Exit;
  // end;
  Application.ProcessMessages;
  Form2.Memo1.Clear;
  Form2.Memo1.Lines.Add(IntToStr(TotalFileSize.QuadPart));
  Form2.Memo1.Lines.Add(IntToStr(TotalBytesTransferred.QuadPart));
  Form2.Memo1.Lines.Add(IntToStr(StreamSize.QuadPart));
  Form2.Memo1.Lines.Add(IntToStr(StreamBytesTransferred.QuadPart));
  Form2.Memo1.Lines.Add(IntToStr(dwStreamNumber));
  Form2.Memo1.Lines.Add(IntToStr(Result));
  Inc(iCount);
end;
 
procedure TForm2.Button1Click(Sender: TObject);
var
  Src, Dest         : string;
begin
  iCount := 0;
  Cancel := False;
  Src := \'D:/Tools.rar\';
  Dest := \'E:/Tools.rar\';

  if not FileExists(Src) then begin
    Memo1.Text := \'文件 \' + Src + \' 不存在!\';
    Exit;
  end;
 
  CopyFileEx(
    PChar(Src),
    PChar(Dest),
    @CopyProgress,
    nil,
    @Cancel,
    COPY_FILE_RESTARTABLE);
end;
 
procedure TForm2.Button2Click(Sender: TObject);
begin
  Cancel := True;
end;
 
end.