数学建模社区-数学中国

标题: 在WIN95中实现文件拷贝的编程方法 [打印本页]

作者: 韩冰    时间: 2005-1-26 01:29
标题: 在WIN95中实现文件拷贝的编程方法

1 M: Q( N& n1 a! L' d

湖北工学院图书馆计算机室

5 j- r* N# J2 H" _

张明武

7 w! u$ n1 }% V) U& Q0 {" g3 E6 @/ `

6 [: Q0 h, ^/ K. E

---- 在Windows中实现文件的操作主要有两种方法。一种是直接利用CFile 类的

0 _% v% ~- w" w- H8 i7 C

操作成员函数来实现,它要用到对于文件操作的底层操作方式,如READ、WRITE

5 O: c! x/ y3 t/ U* W" d

、GETLENTH等,并且要直接操作文件的属性,如创建、读、写等;而且,其缓冲

) P3 G( g1 k$ m+ Z' z- ?9 V

区的设置对于文件的大小和不同的计算机是不同的,特别是对于长度很大的数据

2 ~) u4 b9 h8 f' R

库进行备份,很难达到最佳效果。

3 a- c5 C. D1 g5 C! j, Q

2 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

0 Q8 n) q6 M9 j/ n9 i$ P

---- 本文分析了Win32外壳API对于文件操作的原理,并利用Visual C++6.0实现

4 x6 }5 ]# f) ]" U

文件的拷贝操作。

* w& Q) e3 a" z' I

- G/ \* t1 Q+ ^1 ]# R y- n- Y

一、 原理与结构

8 o& X5 h8 T8 a1 H d

9 ~5 k& S: L E q

---- Windows95/NT中提供了一个API函数SHFileOperation(),它只有一个指向

" d: F4 \( n: U% Z% Z5 R1 ], A

SHFILEOPSTRUCT结构的参数。SHFileOperation()函数的原形如下:

" E* j( w: I" u8 i/ h: L) F- b

/ j# r+ E- G3 H% [

---- WIN SHELL API int WINAPI SHFileOperation (LPSHFILEOPSTRUCT

5 s6 r9 w& v# q& m

lpFIleOp);

( g) ?5 q% ~9 B1 }) m

' D9 p' O% A$ H: G) e c

---- LPSHFILEOPSTRUCT结构包含有进行文件操作的各种信息, 其具体的结构如

& D! d. F, m* p n$ {$ |/ b

下:

# C- w+ A5 X: U: R( i

# s [2 u$ H# k( O9 f i

Typedef struct _ShFILEOPSTRUCT {

: h1 K6 n0 Z0 w

# ]# p0 X m/ Z- |

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; //源文件及路径

7 M2 ?5 t0 g% `6 q. }; ^6 D3 _

7 t9 H( j: M% y2 r' C" u

LPCSTR pTo; //目标文件及路径

% u3 W ^( D* V. q. Q1 v; P& m$ q" `

- H. P* k) ^6 \9 f

FILEOP_FLAGS fFlags; //操作与确认标志

2 V- W5 W# W- d6 ~2 D. W

0 v) K$ X( G( h/ S

BOOL fAnyOperationsAborted; //操作选择位

- \$ B5 T7 u/ i

T! [7 m0 h8 a

LPVOID hNameMappings; //文件映射

; | @! F/ }# @$ Q* m

1 D5 W: K' ?5 T; z

LPCSTR lpszProgressTitle; //进度窗口标题

+ R! [. _1 x6 u2 b/ B) n0 u

2 l# o) w/ L7 n: l

) O) x+ y; O7 E+ K8 B

} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;

( s! `; O% V3 d8 H, _5 Z C9 W

; @* H0 ]* W t0 q

- 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 [( }

个,则应是:

5 P1 Q. r: ? C% V1 f

/ Q% w4 M* ]/ P' z' m

char pFrom[]="c:\\windows\\command

% h* s. ~5 p5 p! k. I. M

3 {7 j4 P& y. m! ^0 C' }

\0c:\\dos\\himem.sys\0"

5 ~$ W9 d l: J- ~8 ]% p

; Q3 Z& B) t& a0 C8 Y( `% z

---- 它表示对c:\windows\command目录下的所有文件和c:\dos\himem.sys文件

3 L# F; {$ F R5 T) e$ `' n8 K

进行操作。'\\'是C语言中的'\'的转义符,'\0'则是NULL。wFunc 是结构中的重

5 ~+ `* n( [7 T5 |7 }

要成员,它指出将要进行的操作类型,是下面的操作类型之一:

' K* |' v- \1 M; \

& B3 W* s3 _; s h: O0 h: p" n8 {

---- FO_COPY: 拷贝文件pFrom到pTo 的指定位置。

v( x3 z. `4 R$ B

5 `# t2 ?- B' h6 e+ U- @) v

---- FO_RENAME: 将pFrom的文件名更名为pTo的文件名。

5 X$ g) }1 P3 Z; z5 I5 M* F

0 B o# Z5 v. p2 n9 P6 B2 f

?( G5 c" |2 m; j1 m

---- FO_MOVE: 将pFrom的文件移动到pTo的地方。

2 h D1 ~) m: C' ~4 V5 |

3 T3 R% m* v p1 Q' ^

---- FO_DELETE: 删除pFrom指定的文件。

5 @; r# L# `, P* k, K

8 b1 W, ~& F. I6 C$ g% |

---- 在进行文件拷贝、移动或删除时,如果需要的时间很长,则会在进行的过

' [0 K4 b, }. R+ a4 Z

程中出现一个无模式的对话框,可以显示执行的进度和执行的时间,以及正拷贝

0 s3 o5 ], \" U+ R9 _; j2 I

移动或删除的文件名,成员lpszProgressTitle显示此对话框的标题。fFlags是

3 _" J) ]( p2 K6 x

在进行文件操作时的过程和状态控制标识。它主要有如下一些标识,也可以是其

/ _" M) i; T$ \( ^$ t) w

组合。

( [: C9 w# Q: F# M3 a

z! G- x3 m! l/ p, ~. X

---- FOF_FILESONLY:不执行通配符,只执行文件.

. M" r1 R. p1 u/ o) ]# }

2 M5 A, i/ ]( h% c+ ?" {

---- FOF_ALLOWUNDO:保存 UNDO信息,以便恢复.

) q' D0 A+ r" I( P- _

* z9 \, Z/ t( S5 t! K/ h& J( o/ g

---- FOF_NOCONFIRMATION: 在出现目标文件已存在的时

' ~5 q- d2 e% e/ P! n$ A

候,如

9 ?' I; r. k8 D4 w" d

果不设置此项,则它会出现确认是否覆盖的对话框,设置

, t+ W4 i+ ~2 n/ j% M+ j/ M' X

此项则

# s2 |9 {7 V& }9 r# G8 T( b1 O8 q

自动确认,进行覆盖,不出现对话框。

& k2 p: \4 X7 S' P: R

6 H8 } v' v% j( @- k. d/ r

---- FOF_NOERRORUI: 设置此项后,当文件处理过程中出

2 a; D1 }1 s; s" J; T

现错误

9 @4 D9 t8 u+ z+ d: v0 u2 |$ z

时,不出现错误提示,否则会进行错误提示。

: t2 |4 ~) g2 ^, u

/ b: | V. F% U+ d7 C

---- FOF_RENAMEONCOLLISION: 当已存在文件名时,对其

/ l! q- P, d/ F( U7 f* o/ W/ y

进行更

% a K! _" E; n& j4 X; a; ]

换文件名提示。

+ Y9 ~& x/ d: e- z- R R% W7 F

/ Y5 c& R+ ^- N7 t. x; C' L1 L

---- FOF_SILENT: 不显示进度对话框。

5 z' l" m) ~, v5 H& P

5 G- y% Y' r/ g) x

---- FOF_WANTMAPPINGHANDLE: 要求SHFileOperation()

& g1 m. p7 y. e( N$ X$ n4 L3 h( ^6 }

函数返

7 S: L% G0 g3 M3 A

回正处于操作状态的实际文件列表,文件列表名柄保存在

4 l& p# N6 x z1 H! ?* m

8 Z6 S s8 Z+ Q0 U1 H O

hNameMappings成员中。SHFILEOPSTRUCT将包含一个

5 n# o1 W( ^% ?$ b |

SHNAMEMAPPING结构的数组,此数组保存由SHELL计算的每

R) O' ?( r! H+ v- A

个处于

+ C$ s4 M6 b( L D9 I! X' E- S

操作状态的文件的新旧路径。

% O, R5 D/ @; u: w+ G: Y) r2 T' h" \

8 h: q; U/ H: ~* s3 r9 g

二、 实例操作

; 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,新建一个

2 L$ `9 k. t5 N) ]7 {/ X# U( C! L

工具条IDR_MYTOOLBAR,设置一个工具消息ID_FILECOPY,并在主框架MainFrm.

5 a+ ?0 w# @3 H5 \

cpp的OnCreate()成员函数中加入工具栏。

) b- H6 Q' J+ U% g+ f! y

$ A$ x# G6 G, Y) k x6 T

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))

8 i" s( P: b! }, X

, c& C+ T3 k& [( Z- m1 l

{

7 C( T' ]3 E% L) {2 {1 |

4 O$ `+ L/ c) }3 u

TRACE("can not create the FileToolBar!\n");

) f& k b6 `7 k) v; e* a5 Z" `

$ p: R: w7 ~ i1 t6 | C6 w0 F

1 ]- K# Q: j; E: A

return -1;

+ |$ G0 U5 G5 e: k1 k x

. 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( i

ID_FILECOPY新增消息处理函数OnFilecopy。然后在处理函数中加入下面程序。

# i5 \+ |: c7 M W/ R6 Z; W

/ P; _! }: \6 h7 J" X

void OnFilecopy()

7 m0 h6 G# [: d% i, V* {

{

1 G- i2 y3 j# J8 R- u7 ]9 M

int nOk;

# z% }; [. p, k3 ^

char strSrc[]="c:\\dos\0c:

' r2 I( _: H) W/ f* x0 `. D

\\pwin98\\command\0";

! 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";

. }/ S* \% c1 D* d/ @( a

//设置目的路径

: X5 R0 w, ]6 {% n. A6 H- U( g

' M: h( v7 ~) X* {1 G S

char strTitle[]="File copying";

5 `7 B# \" [8 o3 F

//进度题头

1 W0 N% i" b, K3 B4 S

# n" C+ K' }& C

SHFILEOPSTRUCT FileOp;

* V! F+ X1 T0 }- [* f3 w

4 }: J% H4 L$ r0 g

FileOp.hwnd=m_hWnd;

* A! k d9 G5 F. l4 W, e; q V

$ `7 R0 _$ `, G. `; P' ~* u: |! @: F

FileOp.wFunc=FO_COPY;

: r8 f: d9 g4 W

1 q B, z& U: s2 c0 T" ?1 y0 W

//执行文件拷贝

9 g) T+ _5 h0 f" y/ f1 E& p2 H, z- O

5 j5 V6 ?# W a3 K

FileOp.pFrom=strSrc;

5 ~# y4 i# g& @4 f

3 Q+ c9 i2 T* s4 |$ e+ I: A2 h

FileOp.pTo=strDst;

, C p$ e7 x; p) B; m S. G: I

3 F# j: w+ K% o; A) p

FileOp.fFlags=FOF_ALLOWUNDO;

# o4 r9 \# H* {: R( s% z

( Y6 y+ \$ K" c: v" H

FileOp.hNameMappings=NULL;

" u8 V8 g0 J% t O2 c

- R9 j/ K7 H& g- Y0 G! n( d. d) P& L

FileOp.lpszProgressTitle=strTitle;

2 X) c- r/ o0 {) u4 d

; t0 c6 Q( V5 G: _9 M# L, u

nOk=SHFileOperation(&FileOp);

- F% Y/ Y. l3 q& ~

9 k9 D V3 w* o1 ^& J

if(nOk)

% i6 {: s! {' d6 y/ i6 V

: h1 w; n; v) K% H

TRACE("There is an error: %d\n",nOk);

" q* p5 ]5 o3 Z g$ `$ z5 x

. p* r5 z8 Y3 q) u. t/ V8 k c; c! j, k

else

+ P" b3 Z5 n% s+ `3 j

! {7 [9 ]+ K* ?) m" g5 `8 I

TRACE("SHFileOperation finished

& l# X& B, w. }7 F! F6 r8 S

successfully\n");

4 o+ U6 O* F( N2 D, ^ _

9 S, R/ S1 z8 `# y; O. f5 `# k

if(FileOp.fAnyOperationsAborted)

' X, Y: o) T# [2 q, d4 {/ o2 Z* I

0 ]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

: A0 j4 T2 K% X5 f4 j7 E3 g2 I' Q

* @% m* |) @# f5 }, Y2 V A

三、 结束语

4 |' c$ N8 o: O6 x6 O& W

9 a: g" V3 H$ x

---- 利用Windows API进行程序文件操作设计,它直接调用Windows操作系统中

3 T8 M. c% T6 e( ~6 D

的外壳,它的处理过程与Windows95/98/NT中的处理过程是一致的有利于我们在

; F0 _" g. _$ v

系统程序设计中保持与操作系统的一致性;同时,由于在文件处理中它是直接调

7 U5 s, m( M$ c9 }# B

用WindowsAPI函数,因此不需要其它应用程序动态链接库DLL的支持。

* x% v& y$ v( j4 A2 f* D' z* }

. \$ c4 F0 W- \& \

---- 在各种开发软件中,都提供了对于文件的各种操作方式,但是它必须利用

+ E9 F) A2 |# X f& Y* O2 k8 i

到文件系统较为深入的知识,而且对于其操作的直观性方面也需要开发者进一步

* ?/ c0 E3 c8 d! L$ D) F

地设计,因此利用操作系统SHELL进行程序设计,不失是一种好的设计方法。






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5