数学建模社区-数学中国

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

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

' f1 m" ?9 R$ i# F9 R

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

: k; b# }( N% Y" W+ Q

张明武

2 X8 P" L, S S' U, m2 L" u

0 _! ~4 @7 C: q! t! N

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

. [+ U& ^# t; S" C9 j& [

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

! F# j+ D3 |5 Q

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

/ C; Y( N1 o2 N3 D* K

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

" R( I( a# l1 d# `& n% F" s

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

" l* N* b: a2 v& O* w

2 {8 G2 G U9 W$ P& C0 U+ R

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

; w& J4 T0 s# X* N

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

, f6 b+ f' c" O

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

3 z; O6 J* }8 }* u2 i0 z

7 Y* v6 C; n, |+ ^! D

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

: d, I2 n/ @" |. {* q& Y

文件的拷贝操作。

: z% ]3 O7 _' p' G

/ Y' b0 f2 ^" z+ W F* W

一、 原理与结构

8 k1 X7 e8 ^. H! F C

$ f4 b8 p1 R/ `6 s

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

7 n: U$ J& U; C8 o6 t- M! ~

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

/ D5 E5 l: @9 Y H) p

; J* e/ k' U0 N5 `

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

( C# Y1 }2 ~1 P1 Z! E, }. C

lpFIleOp);

) `7 h: M! \% l# m& A! _( K

$ o! N2 |' Y9 T0 O6 j

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

0 K0 ~1 f# u5 \9 J; d3 K' B/ | P/ X

下:

) s/ L, E" G8 ~

& F7 }1 ^0 k, [# ]$ x Z

Typedef struct _ShFILEOPSTRUCT {

& l/ R+ N* H; ~( A7 H/ X2 ?

& @: x- m( a( g0 ]9 E% R+ i$ E( k

HWND hWnd; //消息窗口

0 u6 t1 R7 T4 L; z% X* d. }% X5 ?. h0 ]

9 i& ]/ C' d/ f

UINT wFunc; //操作类型

7 {; E2 \% t1 X5 a$ q+ |* A

t' D9 A8 A0 M8 u' J. r/ W$ S( F

LPCSTR pFrom; //源文件及路径

9 a4 y& v0 \: d9 e5 Y

) l. A% p! \0 ?/ G

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

; l/ t, i2 ~' X1 X' q

5 r8 e; v0 K( A

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

! g6 |$ U+ a/ Q+ D$ D

- R3 y% J) e2 ?- U2 N

BOOL fAnyOperationsAborted; //操作选择位

2 \: G5 W$ {) o8 ^, g

; C- w* V% t4 k! p: Q6 ^# ^* u

LPVOID hNameMappings; //文件映射

; Z+ Y! j {0 I; v6 P

3 ]3 \) S( N2 R9 X/ q3 R- r

LPCSTR lpszProgressTitle; //进度窗口标题

8 H0 h! Q) }3 b I8 h3 \5 R

* ^2 e& V$ I3 x, V/ b0 X) z# v

9 X; t. _" B9 d* U8 w& s5 v

} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;

9 T$ B' c. t/ C2 v* n4 Q) B

$ x, }1 E) j3 ]+ W* B3 R) x {

1 K) W, @+ u, u& f

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

2 B7 E' U: M7 |+ j8 Y; O7 R

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

9 b; t3 e3 e# @3 |

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

5 e$ o+ y1 ~2 I

个,则应是:

# u" |$ Q9 c+ N& [" ?2 p: I* U

$ D0 w8 n: |, M6 C1 J

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

/ c5 D& W9 h! R

- m( L$ T# X1 t( n( O* i* l

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

& }9 q( p! D& s2 p: q1 @

0 S6 w+ p b# l. S8 i' w& `

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

' K; U' S2 U6 a9 Z- V& f/ Z

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

. }- @/ i! {' i5 o6 A

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

* f' o+ f* {9 a3 G; j

) V# y' N% [0 W

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

" C. ~1 [; G7 z! ~! ^1 v( G) G

+ t i' A5 g6 Z2 w2 k

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

! t7 z& \' _6 g$ |: S

3 p) B5 w* I3 n

6 n) F! P, l0 Z7 i* u# z

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

6 b! j- R7 m" X8 H

" g4 N# C7 i3 z: H0 h- z# U

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

3 k: @- c) F3 B8 s# D

1 n+ N0 M, T6 a" \+ ~

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

2 T! |- Y, [- x8 i0 n( ]

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

5 h* Y! J3 {) r' `# [6 R* S

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

2 q7 F4 \/ L+ b7 |8 |; S

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

$ V% }3 s* b$ U9 [" ? O# m

组合。

# @9 b, g. p d T

$ S: o! @9 X3 E3 u

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

/ A y7 @& |1 T: e5 ]) X

6 r6 z. ^: u! i, h" d$ {

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

7 @ R, Q2 w F$ ~. c) v

% c: m( a( \0 i5 j# X2 `# F

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

1 C2 y- j2 y& C

候,如

4 a9 W& \9 w5 ]* i: r

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

- x5 V* n7 j( \- m$ {

此项则

$ c/ k9 i1 l+ C- ?

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

V% A1 P4 b* t* D* C% [+ ?- }7 L

4 }0 f( b; Y# E6 E) y; F

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

2 {9 O6 t( C8 ~ A) U

现错误

" @$ }7 V# C0 Q/ E( P

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

/ v+ n; H1 L1 ~& b# j- h

% Z. t8 f- |9 L% H9 _

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

( I. v1 q* N# O6 |- M8 P# q

进行更

: l$ `/ F7 S8 r: I5 {- C1 K& A

换文件名提示。

& T. U, j9 u# e

/ I3 M* ]0 C% z. j. Z, P

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

8 r! B( z/ k3 t* E. T1 l- d2 V5 G

( z. g3 P1 t$ O2 h

---- FOF_WANTMAPPINGHANDLE: 要求SHFileOperation()

: V7 [8 H4 e# R( z r# i' m# y! k+ h

函数返

+ z$ d! g1 [0 g0 A* V$ G

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

; `; K( N$ L ^7 s: g3 F. ^: @

, j8 i/ f" B/ {

hNameMappings成员中。SHFILEOPSTRUCT将包含一个

3 V+ }0 y$ i! `

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

, k; X* Y/ o U

个处于

3 d& [2 {% i. j4 z

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

* n" e; e& w! ~" N% U

" p1 r0 H7 }& S: U

二、 实例操作

+ b- |5 \$ k4 j0 x9 y9 R& E

, Q1 ~ }, e2 K' I" G

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

4 J1 A0 B1 N8 @! e- p, w

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

: Y/ V. h1 d3 h4 Y; ]

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

: U2 R9 } ^& G k& V, f# _. C4 ~

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

3 o8 k( D( n+ E& s1 y% b

& ]% L- m+ [1 d7 G6 O' d" @( O! [

if(!m_wndMyToolBar.Create(this)||

! L# Y$ A) |5 m! P1 u; u) J+ r* O

% Q0 l" E' R0 T& B! S

!m_wndMyToolBar.LoadToolBar(IDR_MYTOOLBAR))

$ h C5 f, K- R0 `: E8 d

& M7 }+ Z( A8 z/ b, z

{

# }3 a$ Z3 ?! i2 t" O7 m9 N/ F: j

3 Y ~- ~9 U9 G# z( b' [

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

9 }3 q+ t* [" I5 b2 x. K" M

0 l% S: T0 V6 t4 o) x

7 S& F: ?- M- E. d4 Y( o" d+ M0 T6 f

return -1;

( E7 I& S4 v& c: ~6 i

2 }0 t! }' K+ ?$ C1 [/ @

}

3 y# j/ x6 V6 t; E) i. o z

" C4 @! G; B' n2 R% b# ?' V7 o: j

% Q8 V8 f4 u8 ?' u0 o

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

' ~1 r- ]" E: z6 Q

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

1 J5 }1 r9 f' _( [8 O- a9 g

`! s6 v' R; }9 C

void OnFilecopy()

* Y) ?9 I8 f3 y$ @

{

# Z" W$ E) z/ V# i% w% U

int nOk;

/ d6 X- x8 D4 @3 [; J0 x

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

! t/ i7 J/ {; j' S, F; X% E8 B

\\pwin98\\command\0";

5 ]1 W1 ?: p3 q$ C1 d

//可以改变源路径

3 H2 `, A' v0 x- @6 B# q8 ]; _( g

7 ?1 I% C$ n5 v: M

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

8 R; F2 `; z8 I4 P0 C

//设置目的路径

7 [$ a& G& E2 ]

7 o/ n& o9 t0 y8 f6 s* z4 y1 l% D

char strTitle[]="File copying";

3 J [3 ~ I% z/ T# \& m5 ^

//进度题头

& x9 A% X- x2 |

/ g% i2 { r8 E" f5 |

SHFILEOPSTRUCT FileOp;

: m) \# b5 n$ {4 Q( I: \( Q4 n

% R3 V( F8 p0 |) P* F" k

FileOp.hwnd=m_hWnd;

* \; s1 [& c c& d

; p1 k! b7 I- w6 f2 u8 \4 k

FileOp.wFunc=FO_COPY;

: t4 T2 F& z/ _% c4 \9 d

+ W/ @ b# Y8 P g5 h6 D

//执行文件拷贝

4 T( ]- ^3 e% t

7 Z" g+ M3 o6 x# m

FileOp.pFrom=strSrc;

* D6 j f, ^6 c. w4 D" P

' T2 L ~0 J& Q1 H. U3 I3 _

FileOp.pTo=strDst;

% A; R1 F0 G+ g& i

! X; Z! c6 s* _6 f

FileOp.fFlags=FOF_ALLOWUNDO;

- R% o/ J5 m' k

( |/ W# T0 M% a$ g" z

FileOp.hNameMappings=NULL;

+ x \! L# q4 ?2 k4 D

5 @; Z7 [& }6 D" e% I3 u9 E8 X

FileOp.lpszProgressTitle=strTitle;

/ i4 ?" P# D8 O% C2 d* E

( J! z# q9 p4 z* V

nOk=SHFileOperation(&FileOp);

" Q* O7 H6 a; }. ]' g; T# y

6 ?7 M/ Y1 f( l9 X' w& S1 J7 L

if(nOk)

; r4 l6 q2 M8 i* E

# x9 I5 a1 V# M, h& l8 u6 g/ F+ z. j# h

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

( A5 J8 s) b: r: w$ T

# D3 ^+ B5 r; m# A, ^$ }9 h2 D

else

+ M% K8 j2 ` Q, V5 H9 n

# w; j$ q" \+ _: @5 D, U

TRACE("SHFileOperation finished

e) K1 g! J# |" p$ M

successfully\n");

4 \0 d. K/ Y+ g. @' i& }! `

3 e! M5 O. M0 Z4 B

if(FileOp.fAnyOperationsAborted)

% r: b: |$ m$ t. i, E4 J

# R- }; n9 ?' P1 B" c1 V

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

4 d+ B+ T( R" W# k9 D8 v! i: Q) @) h

}

: E: Z3 v% Q8 N8 ^) `0 p- H2 m, N3 h

- }1 |2 n! }8 o# o& R

7 w" i4 w {. i& R$ B

三、 结束语

t# I* S* G! i& _2 C7 I

, F `; u) V9 j- G- }" N

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

9 L9 f( V" P( i( N3 H

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

) V: X# B" l# E8 g% H

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

" D# q' T5 ]+ k. X

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

8 T) ~' _. x; m( D: [8 w

1 k- k) _2 \/ `; `3 z

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

; k; h9 `9 `& M! d

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

- o7 B3 t4 y; `

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






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