数学建模社区-数学中国

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

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

7 N; H' T, v1 ?; e+ M" |

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

8 Y8 m5 B7 _2 E3 ^

张明武

- u. T6 @% e" K0 T7 {

8 h- Y! N7 c9 i2 H/ x

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

) V) K. }2 w. L

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

5 D+ x) E2 @: Q" z

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

+ B' \. q: g, ] V

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

% p m( b" Q) J) [- G

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

- F+ z8 f' L, }3 s, F

* J! }3 \! {% f3 Y7 D4 [. o& ]: {

---- 另一种有效的方式是利用Win32外壳来实现这些对于文件的操作。它可以实

8 q8 t! I# F" Y8 d

现包括文件的拷贝、更名、移动及删除等,并且可以支持通配符(如*和?),也

4 k& r7 \( R, ]: ~) q

可以直接对一个目录或目录树进行操作。

+ q- e0 f6 x# e& w

5 G( W" i Q2 \. r, C- s) P

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

/ ~5 c+ J. m1 a8 }. j* L. U" D

文件的拷贝操作。

7 E* ~5 G- x2 W4 k& \# F2 q* ^$ i

& v) e3 h# L( N4 o, O/ B; y

一、 原理与结构

) t" \1 V7 k1 q3 J0 j

: }% _$ D+ `! p, m' S8 l

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

6 }1 d5 s2 X: ]8 d" B6 \9 W

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

|$ b7 x& K% B6 c

. q' k! V, `( q0 S$ E) c q, g) P0 K5 B

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

# v5 }3 ?( q/ H( z6 Z% I! L2 A

lpFIleOp);

0 F u, l Z- t( [3 x; r" G

$ \3 D5 Y, U& C

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

% ]! v. |, i& l

下:

- ~7 Y4 ]$ i. L, c

6 \0 w9 n K1 F

Typedef struct _ShFILEOPSTRUCT {

, Q7 _* B: x7 W u& ^

# W; \! }$ C6 y# U/ Z0 u: W

HWND hWnd; //消息窗口

$ i7 R/ g$ R3 ~ P; Z8 O: a9 Y V8 b

( A' r/ s2 q7 w- \/ U

UINT wFunc; //操作类型

8 f/ c/ G* \' p6 x3 q

( n& ^ L" E9 K5 c' G! ~

LPCSTR pFrom; //源文件及路径

6 C7 S v; Q* y, i& r

( A3 U2 Y1 E5 K$ j( e* j- J

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

# Z& Y0 [6 ~+ s

( e+ Q+ g# f# N- x# x7 O

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

; `3 e$ g6 L* U! Q) f8 W1 O

+ K3 P2 n- x: V

BOOL fAnyOperationsAborted; //操作选择位

H- K1 o: Q$ o9 k

" T7 ?7 W0 X+ ?+ T

LPVOID hNameMappings; //文件映射

" r# K3 X! u+ W) p, z3 r/ k

8 @' F$ t5 w5 N8 k6 F* q

LPCSTR lpszProgressTitle; //进度窗口标题

% r' x: T' p$ W0 G# z% ?

4 A9 y* _/ Y" n9 X ?- I# j

$ J# f% k# [, s4 T* g. j; p- g

} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;

8 W2 n3 @+ t' ~+ p

* J: n- h6 J6 N* r- q; h

& A. w1 d D5 J

---- 在这个结构中,有几个成员很重要。hWnd是指向发送消息的窗口,pFrom

$ D$ n- |2 K! H& P+ g, k

与pTo是进行文件操作的源文件名和目标文件名,它包含文件的路径,对于多个

+ U0 o6 } B+ O6 h9 S8 y

文件名之间用NULL作为间隔,并且可以支持通配符*和?。如源文件或目录有两

# l: F4 W k, ^- k5 r3 S' d, ~

个,则应是:

! o" Q1 c! R! @

" [6 c4 t: e* Z9 y2 I" {

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

/ b0 l& x2 ^3 X5 _) i4 {7 P8 K3 Q

, F! }" ?6 J( x& g) p# O W

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

! t0 H8 d I. g1 l3 o6 c \) {( e

: g: y5 R; _- T& J: i4 F

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

m, P1 p, n: H- X' Q

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

) M3 A3 P6 `" [4 v/ X& x! x

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

7 O: o3 |# ?! q; r$ s2 g

, U. l$ ~) d" {$ l

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

; d3 b) ?/ X- @9 I

n& N* ?+ W/ a& b2 R t( z$ B

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

2 N4 i1 l+ l7 R- l' J! o3 h( q

+ h0 z: P8 B$ K* f" c

! @9 W& y/ N9 w

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

5 K7 j9 t1 e4 e

" M2 h& g2 N- X1 T

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

( C* \: P- I7 n3 W

/ s5 ]5 y. u- v! U+ w+ i/ l3 d

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

/ U! x% r( n1 d* k" Y7 z& g

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

7 e A8 x4 M- ]' q. g( t' N

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

" g5 c9 u9 q5 d+ D

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

% s# n9 @6 F! M% h( \) c

组合。

& }! Q0 Y: C* y6 k3 [7 q' |9 l

: \5 Y V& h4 b

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

2 b2 r; @: g0 {& a' A% u

6 [. L R* m$ Y7 Z' _. N/ U1 L

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

9 @6 s+ ?' _5 Y' i% ?; h6 ?! W7 R

, I8 F. Z) }$ Q# k7 y$ I& q4 u4 N

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

' n9 O- Q! E. m, w1 I" [

候,如

7 _/ c1 F. b# P" Q4 s$ a, Z

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

+ { P r" E1 \# Q

此项则

( V- J3 s: h+ \3 I9 F; B6 p

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

4 [& l3 i& S3 C5 d

; T5 _. K/ l0 Z5 `9 u8 w4 f# Z

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

V- O$ G5 a% r' y1 c* A1 `; p# K

现错误

1 |9 E' H3 X# U" N. m

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

9 A% c4 \5 w, \

7 v( ]4 U6 E4 e! e4 n+ C$ T

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

+ O; _2 ~5 t" [

进行更

8 @' d) G1 A' z

换文件名提示。

# n/ O6 P) U* i; ], p

8 B8 z+ H+ t" Y2 m

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

( p& l9 I7 k5 f7 K2 U0 C0 U6 T5 g

3 {8 q" Z3 Z- U

---- FOF_WANTMAPPINGHANDLE: 要求SHFileOperation()

' G$ y# x8 [0 L/ W6 \% Z

函数返

8 Z6 j5 o; C Z4 ^* J

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

, L# {; Q8 g1 m# Q- B

5 @3 T& {) I* Y( u8 s7 i. z: A D

hNameMappings成员中。SHFILEOPSTRUCT将包含一个

# W B: f; {' A8 J/ k' W

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

: T9 t% j- u6 z1 \

个处于

+ Q! M9 F' s( S, o) y) u

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

4 e$ O2 T4 G! w P4 Z6 b9 K8 k1 f ?

- L: y9 `2 @$ ], w% J

二、 实例操作

+ M$ e, O+ L8 W' M! `$ ^4 W' L& ]1 F" q

: v: I4 \ d: s( ?# }& u. ~

---- 本文就一个Visual C++程序来实现文件复制的实例。首先建立一个单文档

" c* y v1 N$ S% g+ ?2 _9 r: q* f

界面filecopy,然后在主框架中新增一个工具条变量m_wndMyToolBar,新建一个

; p* k$ d/ L3 p% U& P) q" ?8 R. j

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

7 i T0 N: T0 q

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

% p0 p4 ~$ a8 n) T( \

% w5 ~2 h+ a5 g

if(!m_wndMyToolBar.Create(this)||

9 [( a e+ a) H$ r" M7 e/ [

/ ? j! t! N, W+ _

!m_wndMyToolBar.LoadToolBar(IDR_MYTOOLBAR))

. m9 ?" _. S, ]: X4 {

/ U2 _7 y; C6 H

{

& K: L& Y, f! \% K8 P* W# Z! \. H

7 f% @ l* D, p; n

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

( {1 O$ ^5 N: U

' E$ ^2 n' M @9 ^% ]4 D

7 I: F5 g- |. u5 p$ G9 s( n

return -1;

4 S# ?* w$ E6 o$ c4 n

; l5 b' f. _7 f. H/ Y1 l3 h

}

' d5 h) H8 n$ ]3 H1 \

& V5 ^, a( T7 _3 {; l( {% s

1 e( Y$ R0 L9 ^9 u0 O: A8 T& B

---- 通过中视类操作工具条IDR_MYTOOL,利用ClassWizard为其 消息

1 g& L' _" c: l6 j

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

, A3 [$ g6 E3 P; P7 I

% @" U6 T% F" R2 u. F' N

void OnFilecopy()

* a" x) d7 R. c7 y% @+ ]

{

) K% O" C0 _5 M" c8 z6 m

int nOk;

0 P9 E" p/ W% h6 W9 [) y

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

+ }- e) I3 B( _7 {6 F

\\pwin98\\command\0";

3 [+ j3 Y* ^. ?2 Q" a. N U

//可以改变源路径

! N, w, X$ M% I

, G8 ?8 j7 e0 h" v3 G) c _

char strDst[]="c:\\temp\0";

8 _8 u8 v" ]* K

//设置目的路径

- r+ ~: `0 N, K n# J1 N. v

& Z9 Q8 ?1 K* l

char strTitle[]="File copying";

9 y) B6 Z( h' I9 D/ H

//进度题头

; I# e. g2 I: J+ |) H- b% f& q

7 v9 m5 I2 d6 U4 f

SHFILEOPSTRUCT FileOp;

9 ~# M1 A9 v* R9 n, ^% T0 ^9 Z! b

0 W; `8 T3 i& y( F1 g* g% m

FileOp.hwnd=m_hWnd;

; k1 |% F. }4 ]$ a/ v

( [( W% v, e( W: x

FileOp.wFunc=FO_COPY;

& Z4 n$ j! y" r. B( V

! U4 k+ x; H- R9 K( g; N# n0 r

//执行文件拷贝

/ |2 o# q' J `! g/ F7 S# O

1 O4 h0 ]7 t0 E( G

FileOp.pFrom=strSrc;

5 A$ S) f5 g u7 A3 Q; P

- ?! g5 }) z! m; ~1 Z

FileOp.pTo=strDst;

4 K) b% q$ G4 T1 l# q2 z

) j& o3 T0 [' [) R

FileOp.fFlags=FOF_ALLOWUNDO;

: v- g( ~: j' W& ^3 X, m

7 k$ ^3 C0 e5 e

FileOp.hNameMappings=NULL;

. N0 v: w* g5 S$ ^$ _; n* X3 C

3 x# y8 _5 Z" k6 k" i

FileOp.lpszProgressTitle=strTitle;

8 `1 r' g* Y# ~. n* U1 k

) y0 k) a- d8 E6 W; W3 d- [

nOk=SHFileOperation(&FileOp);

9 B/ o$ D: K0 A! F2 X" b

. `1 L* W q3 I& w5 J M! g% q. V

if(nOk)

% _- ~/ i' @8 K* Y; K+ d8 e' g

6 G7 F; P8 _. z; f+ a, R( [

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

# e: ]0 F( H0 [' u6 J' E

$ ^7 u, a4 P: w/ `" l7 }

else

1 N/ L+ ?- W. N/ C$ o

5 p2 U) H( v$ v$ X

TRACE("SHFileOperation finished

3 _4 x/ [9 ^0 x

successfully\n");

+ V2 `, D7 ~5 w( n4 D8 P4 b# ~

' ?, r2 y; u3 H, C7 M

if(FileOp.fAnyOperationsAborted)

% b2 v u; m3 M& |7 e

. R; Z( d+ }1 z; ~! m+ g3 ]

TRACE("Operation was aborted!\n");

0 |* W- P# F8 d# ~% i) q; V

}

, m' Q+ i8 K0 U: [8 @

{, z4 N7 c; Y& t1 v) r/ x

# X2 T0 W" d1 Q ^. R4 ^' P& U

三、 结束语

! X- O7 n$ B3 M& [9 T

! C; [. |# w8 q9 m8 _4 o6 @

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

& N) \# z( E: Y

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

7 @: O, v: r% ~, ]# t

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

( e9 _% l+ F# b# p" G( ]( Y. o" Z

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

6 R' d+ p7 N$ m1 N4 b

" j8 ^; ~; V [* w: ]) B

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

& ]( Z; C- M+ N: H7 W8 Q

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

; m K8 g1 w% w

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






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