数学建模社区-数学中国

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

作者: 韩冰    时间: 2005-1-26 13:07
标题: borland c++ bulder的文件操作总结-1
<>、基于C的文件操作
$ _6 I+ M' u, t  t  在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之。</P>! r9 H, _% J7 n1 P$ `
<>一、流式文件操作- {3 |5 [) u' k5 e
  这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下:</P>" [" n: Q- @: }  i; Y
<>typedef struct {4 q# ?  T3 u7 C' p
int level; /* fill/empty level of buffer */
. P$ w& Y7 W- L# [1 i1 Uunsigned flags; /* File status flags */
) g6 s) I1 ]# ~9 a6 mchar fd; /* File descriptor */
7 i% ]3 i/ v, H; ^* r+ D; Y2 t( dunsigned char hold; /* Ungetc char if no buffer */3 ]# N7 s' Q) h; b
int bsize; /* Buffer size */) A$ @, a: c# x% `
unsigned char _FAR *buffer; /* Data transfer buffer */
* X2 E3 H, m( ^9 D  _9 r9 D2 zunsigned char _FAR *curp; /* Current active pointer */
' v- q3 e# ~. z7 }4 P9 Eunsigned istemp; /* Temporary file indicator */- x0 h5 G8 o! G1 @, k
short token; /* Used for validity checking *// m4 [* [- U' a/ l1 h5 }9 n
} FILE; /* This is the FILE object */</P>
9 l' |" x: P8 ?$ A- W<>  FILE这个结构包含了文件操作的基本属性,对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数见下表 函数 功能
3 W: i7 j" R- z. v% R  @fopen() 打开流 5 M* l6 b- p8 U4 d: F! [
fclose() 关闭流 ( \: F' e$ |, @9 y, N
fputc() 写一个字符到流中 1 A9 v& r4 E$ G+ n6 X! e
fgetc() 从流中读一个字符
! k$ d& s$ E' cfseek() 在流中定位到指定的字符
* i' t1 z7 W# z% ], Nfputs() 写字符串到流 . p0 |# H$ d  p) V: c4 j8 T
fgets() 从流中读一行或指定个字符
4 H+ M1 p% G9 q3 bfprintf() 按格式输出到流
0 w3 @4 U* u9 @: ^! S2 afscanf() 从流中按格式读取 7 t# |* o. T% c; M
feof() 到达文件尾时返回真值 9 K/ E' y9 d, B; Z3 _7 D! s7 i
ferror() 发生错误时返回其值
$ }; w- N! ?! y& g. o3 S$ m' ]rewind() 复位文件定位器到文件开始处
9 V2 {$ d9 J/ H* [remove() 删除文件
6 K7 O) g% h" I; V% p- P; n  H; Qfread() 从流中读指定个数的字符
& |5 o/ A0 \9 D7 Y  s4 `2 Ifwrite() 向流中写指定个数的字符
2 Z4 H  g: b- [) Utmpfile() 生成一个临时文件流
  |. s9 b) a  ?3 v# H& dtmpnam() 生成一个唯一的文件名 </P>
. V: f4 N# o+ B) d$ o<>. s1 m3 L- r2 f: l' r
  下面就介绍一下这些函数</P>
( C2 K# g* f# L7 `- n) z) y<>1.fopen()
& f! o9 i0 o5 Y* s& U  fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能</P>/ S" u" x0 S$ Y9 `! Y$ F1 L8 x3 _
<>为使用而打开一个流 8 x5 e/ }9 `5 z
把一个文件和此流相连接 4 }8 b0 K( e. e9 n) a" n
给此流返回一个FILR指针7 B& U3 Y4 O- N; h4 j0 Z  g
参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下表</P>/ W: Y9 ~/ Y6 s1 [# O5 r, L% n1 p
<>字符串 含义 7 R& a" N, C; ]! d% {& c' W
"r" 以只读方式打开文件   o/ `7 U' I& r- k
"w" 以只写方式打开文件 - ]* H) V" E8 k. n; G/ n, L
"a" 以追加方式打开文件 * n8 S; l" k0 [6 _# p
"r+" 以读/写方式打开文件,如无文件出错 7 I: F- a- K# y7 \# z+ ^
"w+" 以读/写方式打开文件,如无文件生成新文件 </P>$ {% D1 R" d: e; A
<>  一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'\n',而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。</P>2 F2 E3 ~+ _$ [% l5 _
<>  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。</P>( z  r7 c2 X2 |+ t8 g
<>  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。</P>+ y) b0 ?' w3 r" p, |
<>  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL。</P>4 n8 I& p0 f! s5 f( K$ l9 |
<>例:</P>
* w2 E  P. M' h<>  FILE *fp; 8 Z4 R: S, R; {) d
  if(fp=fopen("123.456","wb"))2 }' s& C/ ]. y$ N4 U: W- B
    puts("打开文件成功");
% v8 @, W% w% [  else 7 N, K5 z* v7 }- `
    puts("打开文件成败"); </P>1 ~' f' p2 P" z7 o! S  Y
<>2.fclose() 5 E5 S0 S9 M" X  N' O( V5 E
  fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。</P>
" s) V" _  u8 I: S. U- y6 _<>  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的毛病。</P>
/ p# [; K/ Q2 z% E<>例:fclose(fp);</P>0 I' W4 V1 ~( W  T' B
<>3.fputc()
: l: k4 x- h& f* ?, @" `" k' ?  向流写一个字符,原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。</P>
- @% A- v& h5 W! a<>例:fputc('X',fp);</P>  G/ d. V* v7 Q+ h7 q# w. N
<>4.fgetc()
* ^$ t/ V& G3 Q1 ?( \, q4 u8 m: o  从流中读一个字符,原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。</P>* b: r" {4 g6 A2 C8 B+ D' c3 V
<>例:char ch1=fgetc(fp);</P>4 X+ ]5 o9 A! t* E
<>5. fseek()
, f9 o. _7 H: o* g) R  此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是</P>
, u5 J/ ]7 ^) \6 n' j5 E3 ~<>符号常量 值 基准位置 ' R6 l5 @, G# `1 F- \
SEEK_SET 0 文件开头
( \7 \8 f+ M+ [& x4 R/ tSEEK_CUR 1 当前读写的位置 + y8 a" `' J: i0 c
SEEK_END 2 文件尾部 </P>6 K: r" R  Y* S) ^" l
<>例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)</P>- A8 [6 X* l; H' D
<>  fseek(fp,0L,2);//把读写位置移动到文件尾</P>) _$ T" L: x" D3 b1 b) j9 h
<>6.fputs()
+ C- N+ Q+ I' a$ Z/ D3 Y  写一个字符串到流中,原型int fputs(const char *s, FILE *stream); </P>
2 G0 M  I1 }$ j9 I+ d+ j. C<>例:fputs("I Love You",fp);</P>/ v) e) \4 ?2 b. B" W
<>7.fgets()$ `" D! D7 p& t" S3 _9 h6 \) j# u1 p
  从流中读一行或指定个字符,原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。</P>
6 w; Q. H6 J  M<>例:如果一个文件的当前位置的文本如下</P>
. n, S$ C4 [0 u2 @<>Love ,I Have</P>* j' h+ A2 x' S2 p
<P>But ........</P>
7 T& e5 y" w( C' K3 J  y7 [<P>如果用</P>
6 Q- Y5 l  {) {* I, G2 K4 ]" V<P>  fgets(str1,4,file1);</P>* C" J; D! o" e2 b
<P>则执行后str1="Lov",读取了4-1=3个字符,而如果用</P>! p3 Y5 G  O! |: P+ S+ k6 k5 e' Q3 b
<P>  fgets(str1,23,file1);</P>6 F" x& [& v# r2 V) ?8 ^- e/ J; x% u
<P>则执行str="Love ,I Have",读取了一行(不包括行尾的'\n')。</P># L. c( K( I% E+ V) H7 k6 `
<P>8.fprintf()
. I$ `6 |4 O6 Y- M0 O6 e  按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了</P>' C* D) L2 K3 i0 H, J
<P>例:fprintf(fp,"%2d%s",4,"Hahaha");</P>
# g# p8 g4 B) z2 U9 X<P>9.fscanf()& H' l3 M! k" v  {% ]
  从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, ...]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。</P>, U, ~% A, W* X
<P>例:fscanf(fp,"%d%d" ,&amp;x,&amp;y);</P>
7 }+ Q9 c; K+ s/ {- j; f% f8 W<P>10.feof()+ p4 D+ W4 |- e+ Q% |! F4 Y
  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream);</P>) ^% X. s5 u9 ]- I4 k) r
<P>例:if(feof(fp))printf("已到文件尾");</P>
# S/ c) U9 S" A: t: V  e# U& k! b<P>11.ferror()
% ^  L% D+ E' f  f7 H" c4 y: ~  原型是int ferror(FILE *stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是void clearerr(FILE *stream);</P>9 Y( u6 c0 b) R* m
<P>例:printf("%d",ferror(fp));</P>( O1 y1 h% B* ~( r
<P>12.rewind()  w7 C9 |; G: Q# n( t
  把当前的读写位置回到文件开始,原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);</P>) n6 h% b" g% K) z4 u7 G
<P>例:rewind(fp);</P>
% i* z! o  w% z) T1 ~<P>12.remove()/ A" `8 B6 }( K
  删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。</P>
6 ?3 c* }# V3 D<P>例:remove("c:\\io.sys");</P>2 T7 G8 P- d! t4 L8 [) M5 [
<P>13.fread()! |* Y3 ]% r4 ^) \1 a6 w
  从流中读指定个数的字符,原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。</P>
9 o3 v( p- K) P. @7 s<P>例:</P>
: x3 m& i& E- X" M- A<P>  char x[4230];& K! M9 N* C3 r  I1 Z
  FILE *file1=fopen("c:\\msdos.sys","r");  p7 K2 p3 B7 O( }, \; m
  fread(x,200,12 ,file1);//共读取200*12=2400个字节</P>
& C1 ?" ?7 Y5 w$ \) S  J<P>14.fwrite()( ^0 x, F1 O% g( D  V, R
  与fread对应,向流中写指定的数据,原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。</P>4 |% V+ z7 z8 G' X" [; V# W, L. |
<P>例:</P>! A+ h) y0 t, o" n. i" g& I
<P>  char x[]="I Love You";
+ N8 P0 {) S1 b  fwire(x, 6,12,fp);//写入6*12=72字节</P>
! Q+ R$ |6 s. n* c4 Z& R5 P<P>  将把"I Love"写到流fp中12次,共72字节</P>0 }+ S3 j4 V% \$ H& ]) ]3 D
<P>15.tmpfile()  i0 e/ \% k( D8 s" Y2 q
  其原型是FILE *tmpfile(void); 生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。</P>7 o3 |9 d8 E) D) U
<P>例:FILE *fp=tmpfile();</P>; t( Q% T' `& t" w- U9 L% S
<P>16.tmpnam();  R) M+ P6 T( Q+ j  S: ?
  其原型为char *tmpnam(char *s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。</P>
- y0 M) h: }% x' n  [+ w* }
6 T4 }8 z- E5 r) c' c1 J<P>
* u3 x0 }, v) Q' X. M </P>




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