|
- [3 v& Q8 q5 g; Y. X3 Y湖北工学院图书馆计算机室
9 Q% [; Z- {& q4 F张明武
3 _8 x4 e4 F3 C; |& ~. z8 O2 a
$ B: e. B# n( }. D/ K---- 在Windows中实现文件的操作主要有两种方法。一种是直接利用CFile 类的 : t& X. {1 I0 \: f
操作成员函数来实现,它要用到对于文件操作的底层操作方式,如READ、WRITE
8 F+ h. v6 Z4 x9 M4 x5 |、GETLENTH等,并且要直接操作文件的属性,如创建、读、写等;而且,其缓冲
' z& f& I+ Q' d+ B7 N区的设置对于文件的大小和不同的计算机是不同的,特别是对于长度很大的数据 1 z( w& O1 z3 v
库进行备份,很难达到最佳效果。 * [+ t8 f4 b8 Y {8 l0 u
( {% n" G g+ E& x! R( V9 R---- 另一种有效的方式是利用Win32外壳来实现这些对于文件的操作。它可以实 % i$ b) ?+ ], a7 v4 ~* \. j
现包括文件的拷贝、更名、移动及删除等,并且可以支持通配符(如*和?),也 3 C3 W- `, q% q. v$ V9 [
可以直接对一个目录或目录树进行操作。
' x! N6 Y6 i ~( l# U+ M3 e# K 8 f% A( A; i' n$ I$ \. S% x2 N+ E
---- 本文分析了Win32外壳API对于文件操作的原理,并利用Visual C++6.0实现 , y+ E, C, K6 S- M3 l5 d
文件的拷贝操作。 & B1 W% {, ]$ m
: Q( j$ ^% q C; N' l8 D. M一、 原理与结构 * Y: \+ X! K) W+ h- |9 m
0 P3 b4 u! a& k" v" J: K- s- q---- Windows95/NT中提供了一个API函数SHFileOperation(),它只有一个指向
8 R0 u: a/ v# s- q+ j1 v) F, vSHFILEOPSTRUCT结构的参数。SHFileOperation()函数的原形如下:
7 {1 }8 w# Z5 ?" `8 ~
/ T7 F! O; e2 m- U: i. f---- WIN SHELL API int WINAPI SHFileOperation (LPSHFILEOPSTRUCT 1 R( n2 Q6 R! D N% @6 m! f
lpFIleOp); - X: U# t! }, M1 V. {- Q9 m0 e K5 n
! a6 t& J7 N4 m5 @
---- LPSHFILEOPSTRUCT结构包含有进行文件操作的各种信息, 其具体的结构如
$ Q1 P5 R- I0 n0 |7 Z/ J下: 0 i" Y. h6 z+ s1 M d9 W
1 A. u K7 B; H3 c$ n P6 e
Typedef struct _ShFILEOPSTRUCT {
' V/ H9 P; M% a2 D$ `/ _$ K) l4 S
. t( V( J: U$ o HWND hWnd; //消息窗口 9 h" v1 ?# L' N& e/ c: S3 N
0 A( {5 Q7 N9 B, \1 E- D UINT wFunc; //操作类型
7 ~! n. T: j% X4 D) N2 y9 y
( @$ _& X+ z& V LPCSTR pFrom; //源文件及路径
% o( J* b/ F5 r# |# b2 { 5 `/ B! Z% x( Y1 j
LPCSTR pTo; //目标文件及路径
& n' l. B) c% G' q& W) E. }
$ t4 W' z- B' ` FILEOP_FLAGS fFlags; //操作与确认标志 5 h! l. y3 e' a2 G8 y
# a: y B; Q9 o; U8 C5 j/ c
BOOL fAnyOperationsAborted; //操作选择位 4 {; H0 m- j; {
; \! [$ C$ @8 W$ q LPVOID hNameMappings; //文件映射 0 x0 f( M7 R, y l1 z. c
& p8 v$ I$ i3 d8 O LPCSTR lpszProgressTitle; //进度窗口标题
! [- [ X+ S1 e' S- P / q. \7 `) Z9 [: f
6 ^. Z% P# a" H: ]- Z5 `+ L } SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT; 3 g6 h( I2 y& e% [2 J9 X+ C
1 d" l/ l1 ]5 V1 h( V2 S
# f! I9 Q% R+ j6 d: A4 b- P ---- 在这个结构中,有几个成员很重要。hWnd是指向发送消息的窗口,pFrom
1 r0 \# G" P, s3 I与pTo是进行文件操作的源文件名和目标文件名,它包含文件的路径,对于多个
, ]' v' c" ~9 a% ~文件名之间用NULL作为间隔,并且可以支持通配符*和?。如源文件或目录有两 " D# K& Y/ e2 q1 a
个,则应是: * R ]1 ~# I& D3 z1 e0 {
/ Q, }7 a% }( U' P
char pFrom[]="c:\\windows\\command % T H# H! u- g& Q1 |% m0 ` [
; q, v/ i* H+ ]7 T \0c:\\dos\\himem.sys\0"
6 Z+ C+ ]( c9 W% D : y2 W4 x; X) f" w' J. Q7 W6 n" r
---- 它表示对c:\windows\command目录下的所有文件和c:\dos\himem.sys文件
2 Z d# L& {8 h2 i& w进行操作。'\\'是C语言中的'\'的转义符,'\0'则是NULL。wFunc 是结构中的重
5 L9 h9 M5 @- _7 R要成员,它指出将要进行的操作类型,是下面的操作类型之一:
7 p' ~* k* h, }5 D- q
: c6 h2 K5 G/ z ---- FO_COPY: 拷贝文件pFrom到pTo 的指定位置。 8 \ w/ N8 z0 S" z9 l/ H% }/ i
& B( v/ ^! x7 G
---- FO_RENAME: 将pFrom的文件名更名为pTo的文件名。
/ J9 j* }' j( v
# t) F$ z# [; f
% m! j( t# h! I& b4 V! v ---- FO_MOVE: 将pFrom的文件移动到pTo的地方。 ' W2 K( }1 g. }6 i! t$ o2 b3 C
7 T! n$ n) S8 R7 W6 F1 _
---- FO_DELETE: 删除pFrom指定的文件。
/ x P% S% G; T1 x- O
1 a9 o+ i9 p8 f- f4 F" ~8 l---- 在进行文件拷贝、移动或删除时,如果需要的时间很长,则会在进行的过
5 O' C, @6 a* d5 j8 z& ]* E- v9 D$ `3 J程中出现一个无模式的对话框,可以显示执行的进度和执行的时间,以及正拷贝
; ~' G$ L2 T# X* e9 l. F2 Q$ }移动或删除的文件名,成员lpszProgressTitle显示此对话框的标题。fFlags是
7 Z B* G1 E% V在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其
& l/ U9 E, p) B, P Q组合。
! G* b% Z2 }7 Z2 o' @/ w 2 r' _/ U6 w* P, ?3 m
---- FOF_FILESONLY:不执行通配符,只执行文件. * b; c; f3 n' a6 s" A: _: S
; }1 w0 n7 v9 D0 e w. C* ^8 h" G
---- FOF_ALLOWUNDO:保存 UNDO信息,以便恢复. # ^/ d" Y. A. j, z2 D* p' x7 v' I
8 h% j' Y4 q$ D( M ---- FOF_NOCONFIRMATION: 在出现目标文件已存在的时 / `# t/ B, C, i ^
候,如 ; m7 x9 S: W8 @ _' P) p$ F
果不设置此项,则它会出现确认是否覆盖的对话框,设置
* x; c" J% M, q% u' J5 q" v, T此项则
0 o* u; h! `" H. f% W7 [ 自动确认,进行覆盖,不出现对话框。
9 L4 u3 Y- N5 U4 v" j
3 S6 M. k3 Y1 M' N0 R ---- FOF_NOERRORUI: 设置此项后,当文件处理过程中出
- |& u; t9 C9 j! L! t& }现错误
) |! Q3 ?% u9 g# {3 g! a0 i* m 时,不出现错误提示,否则会进行错误提示。
. h4 u/ H% t6 K
4 |( a- [- }8 H6 r/ C ---- FOF_RENAMEONCOLLISION: 当已存在文件名时,对其
3 v% M7 j" T! V进行更
% V# U% v9 x; H. G! x 换文件名提示。 + e/ M7 e$ @! F! B _
7 b/ u2 m( |" U6 ^- Z4 }
---- FOF_SILENT: 不显示进度对话框。 + c# M1 R v* t* S7 @
! L. [" s" V- J7 c$ w8 W ---- FOF_WANTMAPPINGHANDLE: 要求SHFileOperation()
* f2 o& I0 D! i2 a. i( r函数返 4 v: V' f! ]" L+ D8 p5 ?* P& g& R6 Z6 K
回正处于操作状态的实际文件列表,文件列表名柄保存在 + c3 {. O( v- @1 J6 `
; Z5 l4 }9 P8 Q hNameMappings成员中。SHFILEOPSTRUCT将包含一个 . l) @2 E$ k; U- o- R" C; G% H
SHNAMEMAPPING结构的数组,此数组保存由SHELL计算的每 ( {9 A1 V5 }: ?
个处于 ; t3 j4 N) K9 ]6 \* g# t; g
操作状态的文件的新旧路径。 3 x2 H& ?' E: ~& G a6 f- ]
0 Y: ^$ [" B% j8 i" a8 Y
二、 实例操作
) X$ d2 G9 b1 ?5 u1 X 1 F. w" r) ~: J* v) y- F
---- 本文就一个Visual C++程序来实现文件复制的实例。首先建立一个单文档
3 C) v4 N& D0 V2 ]界面filecopy,然后在主框架中新增一个工具条变量m_wndMyToolBar,新建一个
2 d! G/ d/ C$ i& d6 V工具条IDR_MYTOOLBAR,设置一个工具消息ID_FILECOPY,并在主框架MainFrm.
* `' F6 E) U( O$ ^" tcpp的OnCreate()成员函数中加入工具栏。
( y/ H a" u1 i/ N; X3 W$ M % i" v2 R0 f3 d/ Z% W
if(!m_wndMyToolBar.Create(this)|| ) o9 Z$ `5 A2 a+ d& L! u
; u, f$ V4 A8 h3 b
!m_wndMyToolBar.LoadToolBar(IDR_MYTOOLBAR))
- {" h, V2 |- i' J ( { b* }( i* I/ v' n: g
{ * R: U4 s# Q9 P- C, B9 b2 y' l4 T
: d( d6 Y9 u3 u1 s TRACE("can not create the FileToolBar!\n");
8 U9 t- ~* E/ I* F
4 v: r) ~, k9 D# K
8 H4 v7 m' k. I return -1; " t" E7 a6 \" r5 s0 X: D& X
- A. D. J) Q( U6 r; Z! H9 c } B& |( G8 I8 `0 K7 r4 s
+ U( W1 {; n) y: \4 U, |. Q
% D$ M0 C( ~* o. A---- 通过中视类操作工具条IDR_MYTOOL,利用ClassWizard为其 消息
8 M6 P A! G* Z/ z! SID_FILECOPY新增消息处理函数OnFilecopy。然后在处理函数中加入下面程序。
( m- P/ t1 q) e* K! w' g8 b ( P4 E5 E) ?+ i5 N. N) h( ~$ r0 P. [
void OnFilecopy() ; Q6 ^" g4 x; k* L( } }& R8 e
{
1 D, ?! t: k4 \8 Y b2 R int nOk; & r' }- I7 P; ^+ a1 `/ J4 x
char strSrc[]="c:\\dos\0c:
6 w1 F# }% }! X\\pwin98\\command\0";
$ r ?4 i0 d D u0 q+ J; Y //可以改变源路径
) W- C5 e, N$ J* r
; } f6 Y# g4 k E# Q, ~" ]0 t+ G char strDst[]="c:\\temp\0";
: U' I* H$ A$ ]5 R0 s1 h$ \ //设置目的路径
* l6 N1 q( E" L: j
" H, l7 ~! K7 Q% K( ?1 G. f ]1 A char strTitle[]="File copying"; 2 X$ A6 {: X- Y) y
//进度题头
4 J( o; g7 u7 E+ e 1 a7 i+ f/ [1 F4 E. \. _1 y" B2 \
SHFILEOPSTRUCT FileOp; 5 n) m6 i0 o2 [2 o
$ W( o$ K3 ]. U, u1 j+ Y FileOp.hwnd=m_hWnd; , T% j) V+ X2 e Y& g% C1 I
& B5 f- h' ?" s- q
FileOp.wFunc=FO_COPY; 6 ]. T) \8 o! j
; k$ B4 ^/ q3 x( { //执行文件拷贝
! T0 l ?7 g6 m' O' O! n O / `! e7 r2 ^5 ^" U
FileOp.pFrom=strSrc;
5 V# j. ?* e+ p7 q, o 7 p# U0 Y8 v% ~
FileOp.pTo=strDst; , Z+ w; W9 g5 _$ Y1 m" ]
$ G+ e) ]" R" J6 K4 f# I2 Z FileOp.fFlags=FOF_ALLOWUNDO;
! W0 }- i, Z" z; u# ` ! c+ D8 M, N; E+ m6 a( s( T- W9 S: e
FileOp.hNameMappings=NULL;
, y, P" j8 @1 q8 K
d! ]: u- I, h FileOp.lpszProgressTitle=strTitle; ; `1 O; F& K3 w
$ r! c) t, a9 S
nOk=SHFileOperation(&FileOp); 6 P+ ]+ P; i/ V- {5 g
8 m+ j! c+ U$ R. D1 }4 [' l) O' j
if(nOk)
5 O" |; _( d$ ~- b ( M: R1 S w& I( L+ j" i
TRACE("There is an error: %d\n",nOk);
% g6 [1 t1 ~/ [7 f) w7 i8 P3 Y , |) C: q- X; ]
else 7 b8 B: R+ w# L- ?. ~0 f
2 i) Q9 P0 s5 y8 ?& a
TRACE("SHFileOperation finished
: j) L4 ~& v2 @2 v$ n# t4 Tsuccessfully\n");
; E8 v1 N% ]& A, U
z, N( B0 a; ?+ U if(FileOp.fAnyOperationsAborted)
5 P6 f+ g- c. K$ j G5 k8 x% o/ G; W J
TRACE("Operation was aborted!\n");
; f0 R0 Y8 M" C% S! U }
5 K% J- t+ H# k, y! J @' B
% L7 b2 |, v2 z9 j " {' _; Y$ ^, X# V- _; Y* c( X0 t
三、 结束语 5 T& d+ d, H5 x
* h6 ^4 N! K5 V0 P---- 利用Windows API进行程序文件操作设计,它直接调用Windows操作系统中
/ T$ z# E6 n7 t/ v的外壳,它的处理过程与Windows95/98/NT中的处理过程是一致的有利于我们在 0 ^( O% [+ x* z& J
系统程序设计中保持与操作系统的一致性;同时,由于在文件处理中它是直接调 6 C4 l% q. z3 g/ o2 Q. S
用WindowsAPI函数,因此不需要其它应用程序动态链接库DLL的支持。
) Y. |5 [6 Q" h) I- i" R
' n8 d$ m& v# {/ i8 h: e---- 在各种开发软件中,都提供了对于文件的各种操作方式,但是它必须利用
. K& l0 X. i: u. }0 q; D, u. X到文件系统较为深入的知识,而且对于其操作的直观性方面也需要开发者进一步 $ |6 z: R7 h v/ C
地设计,因此利用操作系统SHELL进行程序设计,不失是一种好的设计方法。 |