1 M: Q( N& n1 a! L' d
湖北工学院图书馆计算机室
张明武
---- 在Windows中实现文件的操作主要有两种方法。一种是直接利用CFile 类的
操作成员函数来实现,它要用到对于文件操作的底层操作方式,如READ、WRITE
5 O: c! x/ y3 t/ U* W" d、GETLENTH等,并且要直接操作文件的属性,如创建、读、写等;而且,其缓冲
区的设置对于文件的大小和不同的计算机是不同的,特别是对于长度很大的数据
2 ~) u4 b9 h8 f' R库进行备份,很难达到最佳效果。
3 a- c5 C. D1 g5 C! j, Q2 C" w n/ d! M. |7 r P
---- 另一种有效的方式是利用Win32外壳来实现这些对于文件的操作。它可以实
1 z; S$ H5 n3 I现包括文件的拷贝、更名、移动及删除等,并且可以支持通配符(如*和?),也
2 c: V" R- M3 A! z可以直接对一个目录或目录树进行操作。
; F4 T9 x) \7 W* o+ z
---- 本文分析了Win32外壳API对于文件操作的原理,并利用Visual C++6.0实现
4 x6 }5 ]# f) ]" U文件的拷贝操作。
- G/ \* t1 Q+ ^1 ]# R y- n- Y
一、 原理与结构
---- Windows95/NT中提供了一个API函数SHFileOperation(),它只有一个指向
" d: F4 \( n: U% Z% Z5 R1 ], ASHFILEOPSTRUCT结构的参数。SHFileOperation()函数的原形如下:
" E* j( w: I" u8 i/ h: L) F- b
---- WIN SHELL API int WINAPI SHFileOperation (LPSHFILEOPSTRUCT
lpFIleOp);
( g) ?5 q% ~9 B1 }) m' D9 p' O% A$ H: G) e c
---- LPSHFILEOPSTRUCT结构包含有进行文件操作的各种信息, 其具体的结构如
下:
# C- w+ A5 X: U: R( i# s [2 u$ H# k( O9 f i
Typedef struct _ShFILEOPSTRUCT {
: h1 K6 n0 Z0 w
HWND hWnd; //消息窗口
# J0 u# `8 Y# O- f! r; E. B! s, ?6 w# N
UINT wFunc; //操作类型
6 _8 C; w) E: k: ?/ M1 B( d% Y; O4 p0 {- [ E$ p
LPCSTR pFrom; //源文件及路径
LPCSTR pTo; //目标文件及路径
FILEOP_FLAGS fFlags; //操作与确认标志
BOOL fAnyOperationsAborted; //操作选择位
- \$ B5 T7 u/ i
LPVOID hNameMappings; //文件映射
; | @! F/ }# @$ Q* m1 D5 W: K' ?5 T; z
LPCSTR lpszProgressTitle; //进度窗口标题
+ R! [. _1 x6 u2 b/ B) n0 u
} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;
( s! `; O% V3 d8 H, _5 Z C9 W
- m! @" a+ I9 r, t/ {' q
---- 在这个结构中,有几个成员很重要。hWnd是指向发送消息的窗口,pFrom
, O& p3 P* e' N$ U* a: P与pTo是进行文件操作的源文件名和目标文件名,它包含文件的路径,对于多个
! W' z0 ]$ K+ }+ U+ r文件名之间用NULL作为间隔,并且可以支持通配符*和?。如源文件或目录有两
+ L! u. D; v g [( }个,则应是:
char pFrom[]="c:\\windows\\command
\0c:\\dos\\himem.sys\0"
; Q3 Z& B) t& a0 C8 Y( `% z
---- 它表示对c:\windows\command目录下的所有文件和c:\dos\himem.sys文件
进行操作。'\\'是C语言中的'\'的转义符,'\0'则是NULL。wFunc 是结构中的重
要成员,它指出将要进行的操作类型,是下面的操作类型之一:
' K* |' v- \1 M; \& B3 W* s3 _; s h: O0 h: p" n8 {
---- FO_COPY: 拷贝文件pFrom到pTo 的指定位置。
v( x3 z. `4 R$ B5 `# t2 ?- B' h6 e+ U- @) v
---- FO_RENAME: 将pFrom的文件名更名为pTo的文件名。
0 B o# Z5 v. p2 n9 P6 B2 f
?( G5 c" |2 m; j1 m
---- FO_MOVE: 将pFrom的文件移动到pTo的地方。
---- FO_DELETE: 删除pFrom指定的文件。
5 @; r# L# `, P* k, K8 b1 W, ~& F. I6 C$ g% |
---- 在进行文件拷贝、移动或删除时,如果需要的时间很长,则会在进行的过
' [0 K4 b, }. R+ a4 Z程中出现一个无模式的对话框,可以显示执行的进度和执行的时间,以及正拷贝
移动或删除的文件名,成员lpszProgressTitle显示此对话框的标题。fFlags是
在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其
/ _" M) i; T$ \( ^$ t) w组合。
( [: C9 w# Q: F# M3 az! G- x3 m! l/ p, ~. X
---- FOF_FILESONLY:不执行通配符,只执行文件.
. M" r1 R. p1 u/ o) ]# }
---- FOF_ALLOWUNDO:保存 UNDO信息,以便恢复.
---- FOF_NOCONFIRMATION: 在出现目标文件已存在的时
候,如
果不设置此项,则它会出现确认是否覆盖的对话框,设置
, t+ W4 i+ ~2 n/ j% M+ j/ M' X此项则
自动确认,进行覆盖,不出现对话框。
---- FOF_NOERRORUI: 设置此项后,当文件处理过程中出
2 a; D1 }1 s; s" J; T现错误
时,不出现错误提示,否则会进行错误提示。
---- FOF_RENAMEONCOLLISION: 当已存在文件名时,对其
进行更
% a K! _" E; n& j4 X; a; ]换文件名提示。
+ Y9 ~& x/ d: e- z- R R% W7 F
---- FOF_SILENT: 不显示进度对话框。
5 z' l" m) ~, v5 H& P5 G- y% Y' r/ g) x
---- FOF_WANTMAPPINGHANDLE: 要求SHFileOperation()
函数返
回正处于操作状态的实际文件列表,文件列表名柄保存在
hNameMappings成员中。SHFILEOPSTRUCT将包含一个
5 n# o1 W( ^% ?$ b |SHNAMEMAPPING结构的数组,此数组保存由SHELL计算的每
个处于
操作状态的文件的新旧路径。
二、 实例操作
; Z* `- d7 C- P: t/ C( J. J5 @. c1 }5 a4 R2 _) I2 A8 b9 A
---- 本文就一个Visual C++程序来实现文件复制的实例。首先建立一个单文档
4 z# Q5 b9 f3 e1 z& f% A界面filecopy,然后在主框架中新增一个工具条变量m_wndMyToolBar,新建一个
工具条IDR_MYTOOLBAR,设置一个工具消息ID_FILECOPY,并在主框架MainFrm.
cpp的OnCreate()成员函数中加入工具栏。
) b- H6 Q' J+ U% g+ f! y
if(!m_wndMyToolBar.Create(this)||
. L' g$ L- G& \( u( A7 n2 O5 A9 X# j, C5 p2 I' P( C
!m_wndMyToolBar.LoadToolBar(IDR_MYTOOLBAR))
, c& C+ T3 k& [( Z- m1 l
{
7 C( T' ]3 E% L) {2 {1 |
TRACE("can not create the FileToolBar!\n");
$ p: R: w7 ~ i1 t6 | C6 w0 F
return -1;
. O0 {- J* f# W" H8 y3 _/ X* S9 u1 v
}
; U9 g# W _: L3 M) L1 `3 Q& [3 q2 s: L) d" H4 d* O z: h5 G) c1 x
, k% c$ D# @; ]' r' {
---- 通过中视类操作工具条IDR_MYTOOL,利用ClassWizard为其 消息
% g- {: @$ m k9 o( `& {/ o3 S( iID_FILECOPY新增消息处理函数OnFilecopy。然后在处理函数中加入下面程序。
/ P; _! }: \6 h7 J" X
void OnFilecopy()
{
int nOk;
char strSrc[]="c:\\dos\0c:
! t2 P: |; N5 h8 \9 u: y5 W//可以改变源路径
, H$ P8 M3 Y: Z, K" C, ~4 i! H5 {4 c' s
char strDst[]="c:\\temp\0";
//设置目的路径
: X5 R0 w, ]6 {% n. A6 H- U( g' M: h( v7 ~) X* {1 G S
char strTitle[]="File copying";
//进度题头
SHFILEOPSTRUCT FileOp;
4 }: J% H4 L$ r0 g
FileOp.hwnd=m_hWnd;
$ `7 R0 _$ `, G. `; P' ~* u: |! @: F
FileOp.wFunc=FO_COPY;
: r8 f: d9 g4 W1 q B, z& U: s2 c0 T" ?1 y0 W
//执行文件拷贝
5 j5 V6 ?# W a3 K
FileOp.pFrom=strSrc;
3 Q+ c9 i2 T* s4 |$ e+ I: A2 h
FileOp.pTo=strDst;
FileOp.fFlags=FOF_ALLOWUNDO;
FileOp.hNameMappings=NULL;
FileOp.lpszProgressTitle=strTitle;
2 X) c- r/ o0 {) u4 d
nOk=SHFileOperation(&FileOp);
- F% Y/ Y. l3 q& ~9 k9 D V3 w* o1 ^& J
if(nOk)
% i6 {: s! {' d6 y/ i6 V
TRACE("There is an error: %d\n",nOk);
" q* p5 ]5 o3 Z g$ `$ z5 x
else
TRACE("SHFileOperation finished
successfully\n");
4 o+ U6 O* F( N2 D, ^ _
if(FileOp.fAnyOperationsAborted)
' X, Y: o) T# [2 q, d4 {/ o2 Z* I0 ]0 a6 J, s) F# N0 ~6 d
TRACE("Operation was aborted!\n");
( G3 M) s. h4 p}
, r0 Y1 L( I n# g! d% r. m
三、 结束语
---- 利用Windows API进行程序文件操作设计,它直接调用Windows操作系统中
的外壳,它的处理过程与Windows95/98/NT中的处理过程是一致的有利于我们在
系统程序设计中保持与操作系统的一致性;同时,由于在文件处理中它是直接调
7 U5 s, m( M$ c9 }# B用WindowsAPI函数,因此不需要其它应用程序动态链接库DLL的支持。
---- 在各种开发软件中,都提供了对于文件的各种操作方式,但是它必须利用
到文件系统较为深入的知识,而且对于其操作的直观性方面也需要开发者进一步
* ?/ c0 E3 c8 d! L$ D) F地设计,因此利用操作系统SHELL进行程序设计,不失是一种好的设计方法。
| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |