数学建模社区-数学中国

标题: borland c++ bulder的文件操作总结-1 [打印本页]

作者: 韩冰    时间: 2005-1-26 13:07
标题: borland c++ bulder的文件操作总结-1
<>、基于C的文件操作
* {1 W& X6 ]  v5 ?! |  在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之。</P>1 K2 m/ l$ s6 A0 j6 f
<>一、流式文件操作
0 k9 k# ]$ U* x- u) ]6 B  这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下:</P>
( _$ _' h0 k+ L<>typedef struct {
/ S3 x! S6 T# B) Q5 H$ h4 C8 cint level; /* fill/empty level of buffer */
3 r* V$ C# U* ~* C# Gunsigned flags; /* File status flags */
5 x: x, k+ A5 Q' n7 Y8 e! {* Rchar fd; /* File descriptor */6 p0 L" i" k2 |+ s& [
unsigned char hold; /* Ungetc char if no buffer */" c& I4 O8 a2 r: B7 v6 Q2 S+ g
int bsize; /* Buffer size */( W! c: n3 S5 P5 r. f- o8 ^2 w3 e
unsigned char _FAR *buffer; /* Data transfer buffer */
0 d- r0 g0 m& runsigned char _FAR *curp; /* Current active pointer */
; m+ _; g  t; O* K, H  M4 ~unsigned istemp; /* Temporary file indicator */$ y1 g/ `- L. B1 d
short token; /* Used for validity checking */9 I, k( p) b1 l7 ?% \5 N. I1 T% H
} FILE; /* This is the FILE object */</P>
0 P( X. k) j- {! _' Q6 \) U7 t<>  FILE这个结构包含了文件操作的基本属性,对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数见下表 函数 功能 0 Y% |$ f& M$ ^9 ?+ l
fopen() 打开流 3 l, O' z# n) g1 I& F
fclose() 关闭流
. O$ C9 }! S: J8 H& ]0 pfputc() 写一个字符到流中
/ \) O- c& |  n) b$ m  x0 M/ s. e. Vfgetc() 从流中读一个字符
+ G+ z: s1 G: ^# K/ R: Wfseek() 在流中定位到指定的字符
) G3 w2 X% {/ V: Z0 xfputs() 写字符串到流
9 X% R" J( @* y/ ]. n2 z0 m; ^fgets() 从流中读一行或指定个字符
" E. \/ o+ L2 w5 P4 m) C# r( [1 bfprintf() 按格式输出到流 $ ~9 I, ?2 m7 H  \
fscanf() 从流中按格式读取 ) {, T1 I& l; g7 o
feof() 到达文件尾时返回真值 / M( B0 R5 p- p
ferror() 发生错误时返回其值
: h1 a- Z- m  s0 B/ ?  crewind() 复位文件定位器到文件开始处
9 y9 h# M. J! k( K& \# Kremove() 删除文件
1 X# e2 }0 G8 }3 L4 {) Jfread() 从流中读指定个数的字符
; y( k% X2 I% S( [2 K* |/ T% pfwrite() 向流中写指定个数的字符 ; `9 [& j$ s5 I( j9 f
tmpfile() 生成一个临时文件流
+ ]/ s4 E% Z& \tmpnam() 生成一个唯一的文件名 </P>
' j- X1 J: E: U$ W- v<>+ x& @8 G$ d$ J7 N" J2 o/ M
  下面就介绍一下这些函数</P>% a4 F' ]% G7 N. F4 A" K. y7 d/ v
<>1.fopen()1 Z8 j( P  h$ _4 |$ c
  fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能</P>1 d8 |7 C& m9 m+ Y0 n; o7 x" D
<>为使用而打开一个流
: d+ c" u( v2 N  v4 V/ E. N0 |把一个文件和此流相连接
- Q+ t6 r' n3 f, p2 z% B' R# d给此流返回一个FILR指针
( U, l8 j/ ~* |& r# E参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下表</P>
7 @: [3 M# Y8 r6 D6 z<>字符串 含义
7 d( [7 h: B5 D- R' ?) H0 z"r" 以只读方式打开文件
5 @/ Z9 D! }5 {3 D6 x"w" 以只写方式打开文件 3 F- a! q0 S4 k2 [  a) k6 V2 s3 M" a
"a" 以追加方式打开文件 + T0 z6 p$ t3 G1 g) B" O, I: q( U
"r+" 以读/写方式打开文件,如无文件出错
2 {: f& y) b2 _. R: L- ~3 ?0 \. `"w+" 以读/写方式打开文件,如无文件生成新文件 </P>2 k, Y) q4 R: b7 t6 i
<>  一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'\n',而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。</P>$ d0 Z- S' b& w( F. U
<>  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。</P>) Q9 M  c! p  v. t
<>  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。</P>
& U, z  v+ q+ W  c8 u# C<>  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL。</P>
  ?9 h9 s4 g6 a<>例:</P>7 r, K" [1 Z5 v9 `! g$ q$ _- c
<>  FILE *fp;
5 U% J7 [/ x# v8 o& b: \4 v  if(fp=fopen("123.456","wb"))
6 y7 g6 F8 ^' K8 Y+ k" B    puts("打开文件成功");  o" T& P+ ]: N
  else
; b& N* x7 j- c+ _    puts("打开文件成败"); </P>
' ?9 U: x' t; _% t) f; y% Q" _<>2.fclose() 3 D5 k+ `4 K% E; f  O8 F0 G
  fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。</P>
) M7 Q: V1 ?! {$ b$ R* _<>  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的毛病。</P>
7 S9 f: o1 W6 E: f: o  z0 O<>例:fclose(fp);</P>
, h; G% K# u# X<>3.fputc()9 y$ t7 k& Q9 q2 |
  向流写一个字符,原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。</P>
$ J4 Z; U; T+ \( Y1 Q8 I- l<>例:fputc('X',fp);</P>6 D- V: L- `0 d8 g- M2 K
<>4.fgetc()
9 S9 B" N' a3 E/ w7 L  从流中读一个字符,原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。</P>
# F% E5 V4 J% V  O, j9 i7 A<>例:char ch1=fgetc(fp);</P>6 a- J3 A) Q" c. g1 u( {5 m
<>5. fseek()
' l9 B( g  v# Y2 V. V- r- G% G  此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是</P>
1 w9 f& [$ `+ m( F! v<>符号常量 值 基准位置
0 z/ Z; l% b  cSEEK_SET 0 文件开头 " s3 R- c  }8 a- j
SEEK_CUR 1 当前读写的位置
( [) n; u9 r1 i* w6 W! ASEEK_END 2 文件尾部 </P>
8 `) q: z* [5 B( t6 v- Z/ v  G<>例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)</P>, @: L/ |' R9 I) [$ g0 V- q
<>  fseek(fp,0L,2);//把读写位置移动到文件尾</P>
, B" p5 ^& m- s. f# }$ M& s<>6.fputs()' q5 O7 N4 Q7 O- M
  写一个字符串到流中,原型int fputs(const char *s, FILE *stream); </P>
( W; Y3 V& g# h& K! p<>例:fputs("I Love You",fp);</P>; U0 n/ O5 X9 }! O8 m4 e% [: e1 o
<>7.fgets()* J% s" c2 i5 O+ ]4 R* h
  从流中读一行或指定个字符,原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。</P>
# r! }) S1 t+ R+ f) H! r<>例:如果一个文件的当前位置的文本如下</P>
3 I1 S5 w$ E# f1 K, v+ i7 O6 |<>Love ,I Have</P>
8 E4 j+ ?( Q2 i# P/ M  K<P>But ........</P>
  p- r9 `& E7 r- v( [$ F# k<P>如果用</P>
8 o4 C( Q& k1 V<P>  fgets(str1,4,file1);</P>
/ y1 P. a, J) M! T0 y<P>则执行后str1="Lov",读取了4-1=3个字符,而如果用</P>% p$ S0 `9 D% `4 a
<P>  fgets(str1,23,file1);</P>
- V  n. C# D. W, Y<P>则执行str="Love ,I Have",读取了一行(不包括行尾的'\n')。</P>
# X* q$ t! V( x( v0 {<P>8.fprintf()5 I6 o7 _; F. ~5 H
  按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了</P>; M# N$ C8 ]% y6 d* }
<P>例:fprintf(fp,"%2d%s",4,"Hahaha");</P>
7 N% ^( n3 C% y/ x( z1 z<P>9.fscanf()
/ i: @, f, |1 C2 s$ D# I9 v2 ~0 S  j  从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, ...]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。</P>
- ]2 g) E- f8 R' o* N<P>例:fscanf(fp,"%d%d" ,&amp;x,&amp;y);</P>" c9 E: V' A. W
<P>10.feof()
& T; t: X. M, l& @% t! {$ b  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream);</P>
# S; w$ E9 h% |" ~8 S<P>例:if(feof(fp))printf("已到文件尾");</P>2 ^9 A7 j6 e- `+ q' j
<P>11.ferror()) u8 I" K3 Y+ k4 c$ ]) n; \
  原型是int ferror(FILE *stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是void clearerr(FILE *stream);</P>
  V: m! J" y: w- ?<P>例:printf("%d",ferror(fp));</P>. K% W. ?" j  Q6 S
<P>12.rewind()
% a0 D( A% \" {* ~  w! v) c  把当前的读写位置回到文件开始,原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);</P>$ _; H! A; y  }6 y% W% t
<P>例:rewind(fp);</P>3 @5 r( F! }- a
<P>12.remove()  K" N" A; V3 Q: |4 X0 h9 ]
  删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。</P>
  S) e' v6 F3 k$ R# J$ e# _3 y8 X6 g<P>例:remove("c:\\io.sys");</P>
6 Z. A6 D0 p" R% k% K  q4 O<P>13.fread()8 ^) j1 h' B, Z) p
  从流中读指定个数的字符,原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。</P>- \  J  m  a: M4 F
<P>例:</P>! m* V- H2 l. ?) u' x% J  a
<P>  char x[4230];
. s. O% D* m. r' u( }  {  FILE *file1=fopen("c:\\msdos.sys","r");
  X. w& Z1 R) c6 o0 u. Z# [  f  fread(x,200,12 ,file1);//共读取200*12=2400个字节</P>
0 w, |. G) F* l<P>14.fwrite()
) Z1 g/ }) w( K' J6 i' m0 d( a  与fread对应,向流中写指定的数据,原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。</P>8 R! g) {# j' Z
<P>例:</P>
* b! X, f" ]2 q! X: \' y  g- Z1 T<P>  char x[]="I Love You";
" `% R/ n* K- t  fwire(x, 6,12,fp);//写入6*12=72字节</P>
+ j: N6 |1 H, }/ s4 }) r) d<P>  将把"I Love"写到流fp中12次,共72字节</P>
5 T* d" O+ A1 U$ J<P>15.tmpfile()5 O6 O' W8 r' ~. R# Y# I
  其原型是FILE *tmpfile(void); 生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。</P>
% K4 r# F& S0 i9 }3 w- i# g, [<P>例:FILE *fp=tmpfile();</P>& c6 W: A7 s# `! T8 C+ [! |5 Q, t
<P>16.tmpnam();# S4 d, k7 h' J% o. ?1 b
  其原型为char *tmpnam(char *s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。</P>
# H6 Z/ v3 k3 i; {8 D/ n
5 _6 V2 I  E" h6 [# b# g2 M& U<P>; M6 U6 \) D, }: x2 A' d- R- I
</P>




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