- 在线时间
- 0 小时
- 最后登录
- 2007-9-23
- 注册时间
- 2004-9-10
- 听众数
- 3
- 收听数
- 0
- 能力
- 0 分
- 体力
- 9975 点
- 威望
- 7 点
- 阅读权限
- 150
- 积分
- 4048
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 1893
- 主题
- 823
- 精华
- 2
- 分享
- 0
- 好友
- 0

我的地盘我做主
该用户从未签到
|
< align=left><FONT color=#cc0000><B>文件 e* Y( ^; s w) g
0 K0 `0 m7 c, \, L! H2 W e</B></FONT><FONT color=#ff0000>文件的基本概念</FONT>
# z' e ]" e% e9 o9 x1 m' u 所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。 实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的, 在使用时才调入内存中来。从不同的角度可对文件作不同的分类。从用户的角度看,文件可分为普通文件和设备文件两种。 G0 `5 T K( R# Y
9 R1 s4 w9 ~8 G4 L9 R9 e8 W/ g 普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序; 也可以是一组待输入处理的原始数据,或者是一组输出的结果。对于源文件、目标文件、 可执行程序可以称作程序文件,对输入输出数据可称作数据文件。
; L" |9 t* q5 @- P
( E+ [/ K A, v' ?2 P 设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。 通常把显示器定义为标准输出文件, 一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf,putchar 函数就是这类输出。键盘通常被指定标准的输入文件, 从键盘上输入就意味着从标准输入文件上输入数据。scanf,getchar函数就属于这类输入。 + C# N) y3 Q K* m
# N) p3 e7 X% {# g+ N% x 从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。
) M1 M% O" I/ q) k3 j/ h
+ w2 N* H0 j+ D ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式为:$ \; Y& h% q8 V( @, C! }
ASC码: 00110101 00110110 00110111 00111000
; A/ w8 v, r) D7 V; h0 {2 z2 ? ↓ ↓ ↓ ↓
; p5 a- F5 D/ t s0 Y十进制码: 5 6 7 8 共占用4个字节。ASCII码文件可在屏幕上按字符显示, 例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。 由于是按字符显示,因此能读懂文件内容。
. T Y5 g9 e: H9 _) V- F: ]) `0 }" Q7 E
二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678的存储形式为: 00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示, 但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。# `" E- I: ^8 z" z
J( N. E, v8 p& m( ]9 d, y( f
本章讨论流式文件的打开、关闭、读、写、 定位等各种操作。文件指针在C语言中用一个指针变量指向一个文件, 这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。 定义说明文件指针的一般形式为: FILE* 指针变量标识符; 其中FILE应为大写,它实际上是由系统定义的一个结构, 该结构中含有文件名、文件状态和文件当前位置等信息。 在编写源程序时不必关心FILE结构的细节。例如:FILE *fp; 表示fp是指向FILE结构的指针变量,通过fp 即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件, 实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针。文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。 所谓打开文件,实际上是建立文件的各种有关信息, 并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。* d" w9 H" U* O% }; s) n
& M/ S) X9 Y* n: d2 H! I) e& m 在C语言中,文件操作都是由库函数来完成的。 在本章内将介绍主要的文件操作函数。9 }6 C. m( g: E# M; q0 _
; q* E5 F, s7 j2 x7 Y5 |7 u<FONT color=#ff0000>文件打开函数fopen</FONT>
" C+ _9 b2 Y% F* \, o2 J2 U! v p; i% l& \& D) n: q* V6 ~' i
fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen(文件名,使用文件方式) 其中,“文件指针名”必须是被说明为FILE 类型的指针变量,“文件名”是被打开文件的文件名。 “使用文件方式”是指文件的类型和操作要求。“文件名”是字符串常量或字符串数组。例如: 4 P! c$ ?$ M9 h6 ? L- x, h
<FONT color=#009900>FILE *fp;
u+ r4 f! b& |6 q, Sfp=("file a","r");</FONT>8 ]# f6 g b4 g4 B( d+ f$ p B0 j( o, H
其意义是在当前目录下打开文件file a, 只允许进行“读”操作,并使fp指向该文件。 ? M0 q! F$ n' z" C1 [
又如:
2 ]2 m5 w# ?, L6 [. c# I% y* C<FONT color=#009900>FILE *fphzk
/ n$ N0 R1 u; _7 V& z) } tfphzk=("c:\\hzk16',"rb")</FONT>
$ E- ^4 S" t% ]! Y1 \0 m6 |其意义是打开C驱动器磁盘的根目录下的文件hzk16, 这是一个二进制文件,只允许按二进制方式进行读操作。两个反斜线“\\ ”中的第一个表示转义字符,第二个表示根目录。使用文件的方式共有12种,下面给出了它们的符号和意义。 3 \+ G. z/ E& F0 u0 O- D
文件使用方式 意 义
i7 |* n9 e3 b w8 v) u<FONT color=#009900>“rt” 只读打开一个文本文件,只允许读数据 / x1 O: k P1 _
“wt” 只写打开或建立一个文本文件,只允许写数据
! p6 Z8 d% z8 O9 }* T7 T1 v“at” 追加打开一个文本文件,并在文件末尾写数据1 t. I% ]0 T8 l* z) u: n' Q
“rb” 只读打开一个二进制文件,只允许读数据: ~. [# q9 E, K9 u. l" L! E
“wb” 只写打开或建立一个二进制文件,只允许写数据
& B( _0 h3 x: {$ m" b7 |“ab” 追加打开一个二进制文件,并在文件末尾写数据
4 \; T% O) n- Q) A" R“rt+” 读写打开一个文本文件,允许读和写
% x7 z- b' i e9 c“wt+” 读写打开或建立一个文本文件,允许读写$ g. K8 r: j, M1 |$ T* ^. _
“at+” 读写打开一个文本文件,允许读,或在文件末追加数 据
: K- e/ Q' J8 O6 L7 K$ X“rb+” 读写打开一个二进制文件,允许读和写 3 M8 C4 K8 x' U1 u: a: d
“wb+” 读写打开或建立一个二进制文件,允许读和写7 w. |$ u9 D, ~+ I
“ab+” 读写打开一个二进制文件,允许读,或在文件末追加数据7 A' x8 r' f5 M
</FONT>
& s, K' a" m, r9 h对于文件使用方式有以下几点说明:# M- i" m' V6 K* w
1. 文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是: S e2 P, A2 P4 x
r(read): 读
1 j2 ^) K8 ~: s6 G0 ]2 n/ R' cw(write): 写
6 ^% I6 v' J8 ^9 C8 \; ~0 {a(append): 追加
6 w9 Q+ P- H/ r) I, m% v: `t(text): 文本文件,可省略不写 Z+ q- Q. @/ ~% T* F8 j4 _1 c
b(banary): 二进制文件
& l) H9 A! k/ o) k* V9 A+: 读和写! n+ R A3 k2 V
( p( G; Q0 E; s, y
2. 凡用“r”打开一个文件时,该文件必须已经存在, 且只能从该文件读出。
! l( Y" L/ ~ Y! Z
! b4 b( ~7 N3 N3 c$ `+ h4 s3. 用“w”打开的文件只能向该文件写入。 若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件。6 f W R1 m2 K% `/ s
$ R& s' W" C4 w. C2 @4 Z7 j! z, J
4. 若要向一个已存在的文件追加新的信息,只能用“a ”方式打开文件。但此时该文件必须是存在的,否则将会出错。6 g" W3 g9 `* f t4 v( ]$ b
* \. T% h: {8 g1 r1 H" B: d$ p/ }
5. 在打开一个文件时,如果出错,fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作,并作相应的处理。因此常用以下程序段打开文件:
4 A6 r& W6 v9 r1 H! T2 U1 L% \<FONT color=#009900>if((fp=fopen("c:\\hzk16","rb")==NULL). @5 g E4 s( \. j
{; A- [: F, v0 `$ i* w
printf("\nerror on open c:\\hzk16 file!");
$ Q. {1 L+ E0 U$ u/ n% Lgetch();
6 o/ C& Q# Y& v3 c& |# e; O3 Sexit(1);
2 y$ u5 t- m3 y7 r" g5 y8 s# T0 V}4 r: G% o" k" t1 E* k
</FONT> 这段程序的意义是,如果返回的指针为空,表示不能打开C盘根目录下的hzk16文件,则给出提示信息“error on open c:\ hzk16file!”,下一行getch()的功能是从键盘输入一个字符,但不在屏幕上显示。在这里,该行的作用是等待, 只有当用户从键盘敲任一键时,程序才继续执行, 因此用户可利用这个等待时间阅读出错提示。敲键后执行exit(1)退出程序。
& V! V- h ?7 O7 W7 \7 R. v. s6 E) ]5 a1 |7 Q
6. 把一个文本文件读入内存时,要将ASCII码转换成二进制码, 而把文件以文本方式写入磁盘时,也要把二进制码转换成ASCII码,因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。- K$ \1 P3 x: W1 Z. u3 z& s
+ I5 ]: J7 n3 b9 F- i8 B9 w1 R
7. 标准输入文件(键盘),标准输出文件(显示器 ),标准出错输出(出错信息)是由系统打开的,可直接使用。文件关闭函数fclose文件一旦使用完毕,应用关闭文件函数把文件关闭, 以避免文件的数据丢失等错误。& G5 e2 p9 k9 w: Z3 _
5 f# s' v9 x- W<FONT color=#ff0000>fclose函数
$ h; W% b0 K1 O% ~) d. B, _) F
% ` C' _* [+ l$ E! U1 h</FONT>调用的一般形式是: fclose(文件指针); 例如:
$ N: z+ V/ J- S! h7 d0 h" _fclose(fp); 正常完成关闭文件操作时,fclose函数返回值为0。如返回非零值则表示有错误发生。文件的读写对文件的读和写是最常用的文件操作。
8 Z* H, j2 J6 X0 U% S
, v$ E' ^3 z* p% x0 c. @在C语言中提供了多种文件读写的函数:
0 ^& U8 \, x; l+ n, u1 P% [·字符读写函数 :fgetc和fputc6 Z' F. L# c+ a9 \, ?1 N
·字符串读写函数:fgets和fputs2 `) ^6 `, J- a1 l5 _) o" R7 B
·数据块读写函数:freed和fwrite7 O; k. i# d) N$ W) X
·格式化读写函数:fscanf和fprinf0 f9 `5 `. s% H3 {, J
/ ]- W" J5 U% U, ]
下面分别予以介绍。使用以上函数都要求包含头文件stdio.h。字符读写函数fgetc和fputc字符读写函数是以字符(字节)为单位的读写函数。 每次可从文件读出或向文件写入一个字符。
3 R0 b% }2 o; X- G. K" o5 k+ o3 \# u
<FONT color=#ff0000>一、读字符函数fgetc</FONT>
' Q1 b( \2 Z, U5 v2 D" @+ Z2 w1 m
fgetc函数的功能是从指定的文件中读一个字符,函数调用的形式为: 字符变量=fgetc(文件指针); 例如:ch=fgetc(fp);其意义是从打开的文件fp中读取一个字符并送入ch中。9 f9 m+ H8 l5 ~
6 l9 o& ^% m8 b! y5 q3 b
对于fgetc函数的使用有以下几点说明:5 q4 a, w- ~, Y( [; ~0 s
1. 在fgetc函数调用中,读取的文件必须是以读或读写方式打开的。9 @% p g+ P/ C, w
" P1 l4 z7 P2 L9 V! K# s
2. 读取字符的结果也可以不向字符变量赋值,例如:fgetc(fp);但是读出的字符不能保存。
; h, K$ m i4 }3 B6 C" x; G
/ e( B3 T3 T" F. I) c/ A3. 在文件内部有一个位置指针。用来指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc 函数后, 该位置指针将向后移动一个字节。 因此可连续多次使用fgetc函数,读取多个字符。 应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统自动设置的。
; O; F/ G' w- m, u2 c! X/ H
$ R$ T! Z' t0 }# }1 N/ A<FONT color=#ff00ff><B>[例10.1]</B></FONT>读入文件e10-1.c,在屏幕上输出。& I. e3 @6 m& ^: C
<FONT color=#009900>#include<stdio.h>8 W( s" {% N' o) L! ^' A) K
main()5 ]) H. Z. w/ @/ w' T `
{8 [# o* G5 E( R
FILE *fp;3 Y, a; `0 N# O1 }) y4 D3 N8 F# J! M
char ch;
, B% |4 v" K2 N( `' |4 R: d$ j4 e) ?if((fp=fopen("e10_1.c","rt"))==NULL)7 X$ V3 ~8 l+ ^/ B* p& `
{
~% q- y: x3 F0 `/ u, O9 S" V2 jprintf("Cannot open file strike any key exit!");
+ J2 m3 [4 e' P$ T" lgetch();
; w$ @5 m8 [3 E- H- r5 zexit(1);! w3 V& G/ r! V+ Z
}
1 {' R$ t) O( E0 J; L2 A. Och=fgetc(fp);
- l9 n( d+ |7 X; pwhile (ch!=EOF). k7 O* N' Q4 _& B1 z5 P
{6 w M1 i& f- a: h
putchar(ch); K2 `, {. B% X6 q7 Q- N0 D$ J7 A) h
ch=fgetc(fp);. ]9 o8 D7 Q2 ?! Y
}
0 @) P& m8 t3 @6 H* x* {fclose(fp);
7 {: F% c, c ^2 c3 n}</FONT>
$ u& M; W' X6 F+ |" K 本例程序的功能是从文件中逐个读取字符,在屏幕上显示。 程序定义了文件指针fp,以读文本文件方式打开文件“e10_1.c”, 并使fp指向该文件。如打开文件出错, 给出提示并退出程序。程序第12行先读出一个字符,然后进入循环, 只要读出的字符不是文件结束标志(每个文件末有一结束标志EOF)就把该字符显示在屏幕上,再读入下一字符。每读一次,文件内部的位置指针向后移动一个字符,文件结束时,该指针指向EOF。执行本程序将显示整个文件。
- h% e5 d- N( k+ m4 c8 P0 ]& T5 o1 w' ^/ i$ F8 n& E
<FONT color=#ff0000>二、写字符函数fputc</FONT>1 j4 O* H: H6 c% i D
/ j/ l* b+ L6 l; `' S' Y
fputc函数的功能是把一个字符写入指定的文件中,函数调用的 形式为: fputc(字符量,文件指针); 其中,待写入的字符量可以是字符常量或变量,例如:fputc('a',fp);其意义是把字符a写入fp所指向的文件中。
" Y5 n& ~% i( h# d4 \/ d0 m6 K3 ]" o9 f( V4 t) u* V7 x" H
对于fputc函数的使用也要说明几点:% ^1 p9 `" {1 @) b6 s6 Z
1. 被写入的文件可以用、写、读写,追加方式打开,用写或读写方式打开一个已存在的文件时将清除原有的文件内容,写入字符从文件首开始。如需保留原有文件内容,希望写入的字符以文件末开始存放,必须以追加方式打开文件。被写入的文件若不存在,则创建该文件。4 C4 B8 \& Q3 o- l# r/ Z
8 t8 y a1 O7 p7 L( z" _ j4 M2. 每写入一个字符,文件内部位置指针向后移动一个字节。
! r" c7 R$ g3 Q% P( X q6 D* F' Q0 W
3. fputc函数有一个返回值,如写入成功则返回写入的字符, 否则返回一个EOF。可用此来判断写入是否成功。; q) v5 g/ M( q/ m
. k. A; C) { Y<FONT color=#ff00ff><B>[例10.2]</B></FONT>从键盘输入一行字符,写入一个文件, 再把该文件内容读出显示在屏幕上。
5 B1 ~) E# ^% h7 ?: M& ~<FONT color=#009900>#include<stdio.h> z2 X. p$ Z9 h1 j! m
main()
& @/ i3 p: Q) u# u{$ v. `7 p; C" [* M" s
FILE *fp;. |# e: F; ^4 S9 g, H
char ch;
7 v: r' d, A4 }1 j, `6 k& Wif((fp=fopen("string","wt+"))==NULL); z2 ?+ V) X( q" v* `
{* p/ N5 @" q+ `% i @% {
printf("Cannot open file strike any key exit!");5 h4 n, j) u- Y/ T0 w
getch();" D" i# K" m4 B, ^1 X' B
exit(1);
4 ^. l$ ^* X7 i; o t}
4 G$ ~* J2 o5 r4 ^. rprintf("input a string:\n");, Y0 S: Y: u0 [' S& A2 c6 H7 N
ch=getchar();+ ~+ ?: T% P4 M1 ]& b# R
while (ch!='\n')7 M" M7 `$ W I% w5 C
{4 \- R7 v2 j) Y# x9 a. c& e
fputc(ch,fp);
0 s+ P: {: ?7 ech=getchar();8 R7 p8 k4 c! R+ o
}
, k, i; K5 \) T5 ^rewind(fp);! f6 Y2 C/ y) i I: u4 J5 m+ A
ch=fgetc(fp);
6 d) [! V9 l1 u( g/ _: H$ d7 lwhile(ch!=EOF)
|. p7 l$ e* o, {* m{
5 w! N. L3 t; K' r, Pputchar(ch);
! d) I' C4 _3 ^1 |ch=fgetc(fp);+ n M) q2 X0 e, y6 r/ C% L9 @' ^* c- u& H
}
3 v6 R r5 G* Q$ `! |printf("\n");
( d- f9 \; C4 X/ xfclose(fp);& O9 H" x" n" W7 n* x
}</FONT>
0 }# z- ]" l( p/ D3 \/ C- f5 E 程序中第6行以读写文本文件方式打开文件string。程序第13行从键盘读入一个字符后进入循环,当读入字符不为回车符时, 则把该字符写入文件之中,然后继续从键盘读入下一字符。 每输入一个字符,文件内部位置指针向后移动一个字节。写入完毕, 该指针已指向文件末。如要把文件从头读出,须把指针移向文件头, 程序第19行rewind函数用于把fp所指文件的内部位置指针移到文件头。 第20至25行用于读出文件中的一行内容。! W/ \3 S7 A3 t( i; U" T
& [2 x- W4 I3 e6 t) K/ R7 r q<FONT color=#ff00ff><B>[例10.3]</B></FONT>把命令行参数中的前一个文件名标识的文件, 复制到后一个文件名标识的文件中, 如命令行中只有一个文件名则把该文件写到标准输出文件(显示器)中。5 B+ y# a& C! v/ b0 y- O: ?
<FONT color=#009900>#include<stdio.h>; e. d, m5 X; s( W" e' W$ B2 u$ n+ ~
main(int argc,char *argv[])
. k8 y3 V4 O& t; E9 x7 O$ j* [{
; }1 q' a( `1 f4 G% U5 w8 ZFILE *fp1,*fp2;
0 R, R' z6 v4 cchar ch;
9 w7 s) C) r( S; `. H4 ]if(argc==1)/ r, c. R# B! q9 R
{. h$ O# N7 N+ x: I
printf("have not enter file name strike any key exit");3 I$ C/ u* }9 H
getch();" l5 s- a3 i& P# G# j4 V8 O' s
exit(0);
/ K: H+ K: y& W1 T}" j# ~ j! o& U% W( y s
if((fp1=fopen(argv[1],"rt"))==NULL)- O' F+ _1 Q: `9 w) B* c
{) G6 p6 w. O# p5 m% z( C
printf("Cannot open %s\n",argv[1]);$ t6 v2 j7 H8 n# f
getch();5 U9 t! m {5 ^+ S7 j& G
exit(1);3 q* b+ ? O" v
}
) z& `/ e: Z+ @! o2 V* qif(argc==2) fp2=stdout;
! o. [6 m. V$ _1 g. A+ aelse if((fp2=fopen(argv[2],"wt+"))==NULL)- z& W ^9 |- P7 S5 O/ a; q% A
{
* o$ X, A \; `4 [. e( F; p( j3 r6 tprintf("Cannot open %s\n",argv[1]);
2 l4 b- [5 J6 E+ j |, I, sgetch();
W% I& k: L" d& P& uexit(1);
; |' V9 U8 p5 A7 N! V: t}; l+ F* S ?, V" G+ Y8 v2 f7 Q
while((ch=fgetc(fp1))!=EOF). C6 v2 u8 ~; {4 r* n: T
fputc(ch,fp2);9 D. ]6 X! N5 j' v% l
fclose(fp1);
# l- K3 C& S: C& \; y. X" }fclose(fp2);+ b$ ~, k- I( m0 u& q
}</FONT>
( g8 R* y, H3 H0 L 本程序为带参的main函数。程序中定义了两个文件指针 fp1 和fp2,分别指向命令行参数中给出的文件。如命令行参数中没有给出文件名,则给出提示信息。程序第18行表示如果只给出一个文件名,则使fp2指向标准输出文件(即显示器)。程序第25行至28行用循环语句逐个读出文件1中的字符再送到文件2中。再次运行时,给出了一个文件名(由例10.2所建立的文件), 故输出给标准输出文件stdout,即在显示器上显示文件内容。第三次运行,给出了二个文件名,因此把string中的内容读出,写入到OK之中。可用DOS命令type显示OK的内容:字符串读写函数fgets和fputs
' v* H3 b& ?) }+ h* l ]
2 P2 Y, d; u+ H! E$ X% b一、<FONT color=#ff0000>读字符串函数fgets函数</FONT>的功能是从指定的文件中读一个字符串到字符数组中,函数调用的形式为: fgets(字符数组名,n,文件指针); 其中的n是一个正整数。表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志'\0'。例如:fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入字符数组str中。! W: j3 \. V6 T7 j& T8 H
<B><FONT color=#ff00ff>[例10.4]</FONT></B>从e10_1.c文件中读入一个含10个字符的字符串。
* o% y2 f7 l8 Q$ M1 H' G+ h<FONT color=#009900>#include<stdio.h>
' ^+ H: o% v9 Y, k4 Pmain()5 Y) e6 b0 A/ k$ u2 d$ M, |
{
$ x/ K- ]. i _2 ~FILE *fp;
0 @# [: y4 Q$ ~% u, Rchar str[11];
1 |! R: o# m, a3 kif((fp=fopen("e10_1.c","rt"))==NULL)$ Y4 Z4 f) X2 q& R- G* s
{+ P1 S1 R& T" o2 w" T% c( e- L4 e
printf("Cannot open file strike any key exit!");
- v7 g% g, r# e" w8 o. Cgetch();7 _: p4 r+ p3 [+ O
exit(1);
4 Z1 \1 c: f2 i, z0 X! H- `}
8 T4 k2 ~& P9 w( f' R, W: R" jfgets(str,11,fp);
, P9 r, |- i+ Q; Rprintf("%s",str);
" b, u& v5 l$ ffclose(fp);
9 Z& c% R' G" V; F! x}</FONT>
3 O5 x: f9 ^: s$ R) x/ O 本例定义了一个字符数组str共11个字节,在以读文本文件方式打开文件e101.c后,从中读出10个字符送入str数组,在数组最后一个单元内将加上'\0',然后在屏幕上显示输出str数组。输出的十个字符正是例10.1程序的前十个字符。
* B' V+ R$ E. Z1 v" {. i, d
7 H) v$ p2 L# m7 Q U9 u 对fgets函数有两点说明:
2 v% p& i9 b! {1. 在读出n-1个字符之前,如遇到了换行符或EOF,则读出结束。1 i) c3 Y/ [" U" i: z
2. fgets函数也有返回值,其返回值是字符数组的首地址。
?7 l6 t- N+ z2 K2 @
1 j9 y6 I- m, ?, x<FONT color=#ff0000>二、写字符串函数fputs</FONT>' Q- D% N1 G# G( o
& X; N7 d" P. `, S! v6 ^) p6 q
fputs函数的功能是向指定的文件写入一个字符串,其调用形式为: fputs(字符串,文件指针) 其中字符串可以是字符串常量,也可以是字符数组名, 或指针 变量,例如:+ X/ e7 k& c" _8 y9 N, X
fputs(“abcd“,fp);3 T& M) Z8 r2 r! d1 A2 E
其意义是把字符串“abcd”写入fp所指的文件之中。[例10.5]在例10.2中建立的文件string中追加一个字符串。
9 w/ A: o; H4 m- ]<FONT color=#009900>#include<stdio.h>
1 ?7 C% u' L3 I4 U# amain()9 k" Y/ \4 k h) \
{6 b4 x; U- w/ l9 F: a9 t! t, r
FILE *fp;8 g6 i3 y9 C8 A
char ch,st[20];
& t3 @+ u b1 Z& D6 o$ V. Nif((fp=fopen("string","at+"))==NULL)
4 k/ x9 Q: h7 h1 [8 R* T( L{0 s; [" v; s5 k2 T/ w. s
printf("Cannot open file strike any key exit!");/ S4 z7 V( I$ | H
getch();4 [( I9 \3 r5 I" T; o7 [
exit(1);. i. |: O( D$ E |, s9 f" I
}$ P$ L3 Z+ f0 H' \+ s, W$ H5 f
printf("input a string:\n");2 b: R3 g6 ^3 w7 a; J
scanf("%s",st);
8 K1 k2 d; A4 Vfputs(st,fp);
' ~- L0 j, h) D: z, zrewind(fp);
& x/ {& q4 X; A; y( H. A% wch=fgetc(fp);
4 d9 j& D! m/ K% P o2 dwhile(ch!=EOF)7 |6 s; Y: s6 {. K, H
{# {" W* p% Z0 S
putchar(ch);; o G. T; c* X3 K
ch=fgetc(fp);0 K! y# e+ N% ?
}
+ z$ ^* _7 a* E- lprintf("\n");+ M# J9 S& U0 a# _4 u
fclose(fp);
/ s( V# \9 n6 g1 H# v8 c! I}</FONT>
5 v* Z8 u ~* z6 a 本例要求在string文件末加写字符串,因此,在程序第6行以追加读写文本文件的方式打开文件string 。 然后输入字符串, 并用fputs函数把该串写入文件string。在程序15行用rewind函数把文件内部位置指针移到文件首。 再进入循环逐个显示当前文件中的全部内容。, Z3 [! j2 r( _) Z2 |' S! M: m$ ^
# L' u M9 Z, s2 |+ h7 k
<FONT color=#ff0000>数据块读写函数fread和fwrite</FONT>
4 T7 H6 r- Y' ?6 ?
7 I) _0 C0 |3 `) b# y/ m# ^ C语言还提供了用于整块数据的读写函数。 可用来读写一组数据,如一个数组元素,一个结构变量的值等。读数据块函数调用的一般形式为: fread(buffer,size,count,fp); 写数据块函数调用的一般形式为: fwrite(buffer,size,count,fp); 其中buffer是一个指针,在fread函数中,它表示存放输入数据的首地址。在fwrite函数中,它表示存放输出数据的首地址。 size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。
4 @7 c1 B( B H- Q1 n8 A) ?例如:) w4 |, n& i+ }( u6 l9 u
fread(fa,4,5,fp); 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
5 F9 j; X {; H% d% F$ [! b V5 E[例10.6]从键盘输入两个学生数据,写入一个文件中, 再读出这两个学生的数据显示在屏幕上。/ Q. s- i" X) d1 C
<FONT color=#009900>#include<stdio.h>
8 x5 `- x0 Y P1 L+ x! ?( ?struct stu
! B& |6 t! w" ^% d+ x" a9 ]{
' U5 J# F w C; \! uchar name[10];5 t- L3 H1 ]6 t+ I; ]: @
int num;
4 r! T5 |& @0 \/ a6 iint age;% E+ Y( U5 B0 w' p) M
char addr[15];$ @3 m- G+ I! u7 w* J
}boya[2],boyb[2],*pp,*qq;/ A) P6 f! g' P8 j7 A$ h6 i
main()
) W( ~5 f, u. T% b2 k+ R. T2 j{
( W7 x' c. z6 a9 p# u/ `FILE *fp;. D7 u: E( V8 {" P
char ch;5 `; _: }' V4 J" J' a* N& b
int i;# o0 I( ~! S7 u1 h* j
pp=boya;; S. e& ~7 g* a/ G
qq=boyb;
. }6 B1 x; _7 ^. W) ?, ~if((fp=fopen("stu_list","wb+"))==NULL)
3 d8 V7 S+ K# M{
# Z" e- j. e, ?3 A& j1 _4 b2 \printf("Cannot open file strike any key exit!");* w+ B6 P+ J# H/ R% W9 p0 ?
getch();9 l1 Z' W' [+ H7 ~" T
exit(1);. F. p& D- Q3 L7 D# Y X
}
- s N0 `' |$ ?3 O6 zprintf("\ninput data\n");
5 b/ Q3 l% n6 J: U% k: zfor(i=0;i<2;i++,pp++)
( A% y7 C; y* s$ D8 xscanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
7 m3 y( I, X$ v& Z, ^pp=boya;
3 N4 Q! f! e P2 \% O3 m+ Z/ Zfwrite(pp,sizeof(struct stu),2,fp);
5 B4 G- V3 a! A) W9 Xrewind(fp);
1 i" J; C$ B. U2 p, tfread(qq,sizeof(struct stu),2,fp);1 w; c/ X1 M: k! Q T( F2 f
printf("\n\nname\tnumber age addr\n");
$ _* e* i9 N M, Mfor(i=0;i<2;i++,qq++)
% `) ?- x& B y; Gprintf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);7 d5 a; d5 N0 Q/ b2 A
fclose(fp);; e- E# S' f* _& s
}</FONT>
3 T3 [2 v% k+ H ~! O. G 本例程序定义了一个结构stu,说明了两个结构数组boya和 boyb以及两个结构指针变量pp和qq。pp指向boya,qq指向boyb。程序第16行以读写方式打开二进制文件“stu_list”,输入二个学生数据之后,写入该文件中, 然后把文件内部位置指针移到文件首,读出两块学生数据后,在屏幕上显示。. b8 ^0 E0 s! \& _
& \8 ]5 W9 C+ T2 j1 a' O" Q<FONT color=#ff0000>格式化读写函数fscanf和fprintf</FONT>
. F. m4 ?9 c& B- g; t0 X+ S* ?: N
, s$ T' q* t7 n9 ~0 Cfscanf函数,fprintf函数与前面使用的scanf和printf 函数的功能相似,都是格式化读写函数。 两者的区别在于 fscanf 函数和fprintf函数的读写对象不是键盘和显示器,而是磁盘文件。这两个函数的调用格式为: fscanf(文件指针,格式字符串,输入表列); fprintf(文件指针,格式字符串,输出表列); 例如:3 g. i( u( u3 n$ u# Y9 O
fscanf(fp,"%d%s",&i,s);
0 w9 N$ t( ^) M- N$ x1 \2 jfprintf(fp,"%d%c",j,ch); ' d$ c" Q" \+ U, J, S# _
用fscanf和fprintf函数也可以完成例10.6的问题。修改后的程序如例10.7所示。
2 R% ^0 {& s6 ][例10.7]
3 x- K6 z0 m% M! _$ C<FONT color=#009900>#include<stdio.h>
4 C+ a1 F8 {) \) f( K* L" |: Xstruct stu
+ f% H( _: e2 ]{3 d% D% ]! B |- J" {
char name[10];
( \( L2 s5 f! ?7 [int num;
* P* K9 w v4 a, F1 U8 U2 I7 `int age;* S; E, L6 D: I+ I4 x# X
char addr[15];/ W9 M' t# I! a7 y+ g
}boya[2],boyb[2],*pp,*qq;
q+ e' e4 k: e4 `' amain()
$ c# M# s/ `. O4 e6 Y! s; p9 p{
3 v' D! Z2 S6 h5 w4 u" R. z; V& PFILE *fp;0 J4 j7 ~0 F% Q( L8 W* J p8 V
char ch;
% d: [0 B) N/ K& q9 Y; h5 {3 Pint i;
3 W, a. ^% h. I* r9 y+ g0 Vpp=boya;3 b8 x/ w3 d! g+ M; v4 K
qq=boyb;- z' k! b# H* G) y: w
if((fp=fopen("stu_list","wb+"))==NULL)
# e) U+ E5 T, P& l. h z: [! O{
7 d" S6 F4 y' U% g) Dprintf("Cannot open file strike any key exit!");) V4 [5 k; q; J4 m L
getch();2 B/ Y; u, ]& [8 D2 H
exit(1);' n# r; `6 O& J; B
}% h5 \! Q, x& Y' J
printf("\ninput data\n");
1 V+ M8 s. s+ S) Z& B6 Q# V6 cfor(i=0;i<2;i++,pp++)7 ~# t4 p1 T& r- {
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);- u: x! q. m; C
pp=boya;9 _% y8 J3 m% o2 Q4 G1 q, j
for(i=0;i<2;i++,pp++)$ g' ^# u3 O* }4 Q
fprintf(fp,"%s %d %d %s\n",pp->name,pp->num,pp->age,pp->' z. W- g: z( `: X. M3 q1 R
addr);+ y2 r8 G9 f- t- f8 y
rewind(fp);
* b* T9 s _% E4 l/ G, Ifor(i=0;i<2;i++,qq++)5 w7 E% f( U6 e5 u
fscanf(fp,"%s %d %d %s\n",qq->name,&qq->num,&qq->age,qq->addr);4 W. H: }2 n1 c/ e3 B9 b5 D
printf("\n\nname\tnumber age addr\n");
- Z) v5 s( B& K, {, v* L* mqq=boyb;
) X! P" N' a4 p2 j) f/ k Jfor(i=0;i<2;i++,qq++)
6 {0 `% P# n6 ^printf("%s\t%5d %7d %s\n",qq->name,qq->num, qq->age,
1 c# k+ q1 ?2 ~+ A/ qqq->addr);
2 Y W0 d3 h: Y Q, b9 y% sfclose(fp);( ? ?0 a& E! d
}</FONT>% u e3 }, R: @
与例10.6相比,本程序中fscanf和fprintf函数每次只能读写一个结构数组元素,因此采用了循环语句来读写全部数组元素。 还要注意指针变量pp,qq由于循环改变了它们的值,因此在程序的25和32行分别对它们重新赋予了数组的首地址。
/ L3 |4 t, Y. f1 ^: t1 ~- @8 m5 d* f! m
<FONT color=#ff0000>文件的随机读写</FONT>; O) G; F' d6 s: W7 E
. y' ^ i2 K: E# w( x+ s 前面介绍的对文件的读写方式都是顺序读写, 即读写文件只能从头开始,顺序读写各个数据。 但在实际问题中常要求只读写文件中某一指定的部分。 为了解决这个问题可移动文件内部的位置指针到需要读写的位置,再进行读写,这种读写称为随机读写。 实现随机读写的关键是要按要求移动位置指针,这称为文件的定位。文件定位移动文件内部位置指针的函数主要有两个, 即 rewind 函数和fseek函数。+ U' I8 j2 o+ m: o' l0 A# ]: Q/ h
1 J% V& e4 t |1 r0 x
rewind函数前面已多次使用过,其调用形式为: rewind(文件指针); 它的功能是把文件内部的位置指针移到文件首。 下面主要介绍
8 ?, ~+ s5 q' @3 kfseek函数。9 P+ F2 d: b. o4 A
% g4 a' E( M4 I. C; u$ a fseek函数用来移动文件内部位置指针,其调用形式为: fseek(文件指针,位移量,起始点); 其中:“文件指针”指向被移动的文件。 “位移量”表示移动的字节数,要求位移量是long型数据,以便在文件长度大于64KB 时不会出错。当用常量表示位移量时,要求加后缀“L”。“起始点”表示从何处开始计算位移量,规定的起始点有三种:文件首,当前位置和文件尾。8 r* d/ j' Q- n3 ~4 s
其表示方法如表10.2。 2 j: @: w+ I1 {9 {
起始点 表示符号 数字表示
, }/ K# Y7 k8 q5 B, [──────────────────────────
" D1 d# }% { q3 H- ~6 e r. L文件首 SEEK—SET 0& @" W4 [- R4 Z9 Q D L* f
当前位置 SEEK—CUR 1% V" z |% [% z, t2 b: K9 {* v
文件末尾 SEEK—END 2
, Y. ?, R3 M/ m例如:
4 j9 P; G/ a; G$ G% R9 Qfseek(fp,100L,0);其意义是把位置指针移到离文件首100个字节处。还要说明的是fseek函数一般用于二进制文件。在文本文件中由于要进行转换,故往往计算的位置会出现错误。文件的随机读写在移动位置指针之后, 即可用前面介绍的任一种读写函数进行读写。由于一般是读写一个数据据块,因此常用fread和fwrite函数。下面用例题来说明文件的随机读写。
% \ s0 V. q7 E0 ^( {2 m0 L1 F' P7 J0 [9 w/ s. d
<FONT color=#ff00ff><B>[例10.8]</B></FONT>在学生文件stu list中读出第二个学生的数据。 A0 z% V! I3 g2 T( [0 }
<FONT color=#009900>#include<stdio.h>
% B: w: N, ]! v& [& F4 I" Nstruct stu
* [# T& k- |& k. ?{5 K' ?5 H* s/ ]5 G/ V% f
char name[10];
6 f g- K" w0 Cint num; ^1 b W& @! V# l9 U8 f3 m
int age;
, ?% ^! U% C ?) g1 V0 Fchar addr[15];
& \: C) m& f# D}boy,*qq;1 R% [2 f/ ~- B9 y; Z
main()) w8 z7 g2 T5 t. @! C7 v, y
{
( b4 { ?. f. i0 E4 |FILE *fp;
& U; _& p C9 i% h$ Achar ch;/ r9 W' O6 w0 c4 o2 U0 F; E
int i=1;
( A! G9 S A7 F2 r& o& P3 oqq=&boy;
, c- N. u3 `$ e, O% Zif((fp=fopen("stu_list","rb"))==NULL)
. v! O0 x; M3 o- U9 c{: ?: G P+ J2 w- `! M
printf("Cannot open file strike any key exit!");
3 y" z5 I4 w. u. ggetch();0 s3 x( G1 E! T% i2 z* I. L
exit(1);
/ P" f$ _; o( s a; Y7 s8 v}, {( B: _3 C3 p
rewind(fp);/ `; [9 ?0 F* Z: a$ d& u3 p: P: f4 P. j
fseek(fp,i*sizeof(struct stu),0);' ^% D+ T& \- _, K/ r: {
fread(qq,sizeof(struct stu),1,fp);4 D: K! K& k* k/ W* o: o
printf("\n\nname\tnumber age addr\n");5 q; X4 O4 {( v+ E4 p7 l: W: y! {8 N
printf("%s\t%5d %7d %s\n",qq->name,qq->num,qq->age,0 ~5 K3 A2 w9 B8 {
qq->addr);
* \0 F4 E& ^6 a5 h N}</FONT>
# p3 }3 S0 P: T4 ] 文件stu_list已由例10.6的程序建立,本程序用随机读出的方法读出第二个学生的数据。程序中定义boy为stu类型变量,qq为指向boy的指针。以读二进制文件方式打开文件,程序第22行移动文件位置指针。其中的i值为1,表示从文件头开始,移动一个stu类型的长度, 然后再读出的数据即为第二个学生的数据。
. a" S% V, o" c4 T. `+ c
: D( l1 D- T( }<FONT color=#ff0000>文件检测函数</FONT>
, D7 d7 z- y. x( x! K5 M! b7 }+ x% b% N1 R' \& o: u
C语言中常用的文件检测函数有以下几个。 q8 M" {( H- {6 w/ X0 |
一、文件结束检测函数feof函数调用格式: feof(文件指针); : H7 T [, S6 x% x X
功能:判断文件是否处于文件结束位置,如文件结束,则返回值为1,否则为0。
' h+ D' N! Q/ N/ G* U5 n& N8 T% r6 M* E
二、读写文件出错检测函数ferror函数调用格式: ferror(文件指针); 0 P# q/ k1 v" H( I5 ]" k
功能:检查文件在用各种输入输出函数进行读写时是否出错。 如ferror返回值为0表示未出错,否则表示有错。3 j3 L0 Q% K0 [/ A- k8 G0 R
$ h3 N3 e5 J3 d' b# e4 s3 a9 F
三、文件出错标志和文件结束标志置0函数clearerr函数调用格式: clearerr(文件指针); + J+ R0 f9 X9 M! Y* ?$ d
功能:本函数用于清除出错标志和文件结束标志,使它们为0值。
5 T& H/ n7 U" S- C. s* E4 [) Q7 ^0 p8 @
<FONT color=#ff0000>C库文件</FONT>
' N; |, N7 L" G- F6 i1 S
' _. Q3 d- A/ \C系统提供了丰富的系统文件,称为库文件,C的库文件分为两类,一类是扩展名为".h"的文件,称为头文件, 在前面的包含命令中我们已多次使用过。在".h"文件中包含了常量定义、 类型定义、宏定义、函数原型以及各种编译选择设置等信息。另一类是函数库,包括了各种函数的目标代码,供用户在程序中调用。 通常在程序中调用一个库函数时,要在调用之前包含该函数原型所在的".h" 文件。, b* x( q6 c4 |8 W% x# O
在附录中给出了全部库函数。
( t9 ^+ _* _, t) Q# L3 h4 @ALLOC.H 说明内存管理函数(分配、释放等)。
& G( G0 i% T9 iASSERT.H 定义 assert调试宏。
# x4 m- P) N) ^" w0 IBIOS.H 说明调用IBM—PC ROM BIOS子程序的各个函数。' b0 ?, D: Z$ {& w, ~
CONIO.H 说明调用DOS控制台I/O子程序的各个函数。1 I* d3 E" b( [& M. ]
CTYPE.H 包含有关字符分类及转换的名类信息(如 isalpha和toascii等)。
& M6 h% k# g& W# S# |$ FDIR.H 包含有关目录和路径的结构、宏定义和函数。
' s+ r1 p- W! f) R. [; R& UDOS.H 定义和说明MSDOS和8086调用的一些常量和函数。
: B! O. Q) `5 S! w! B9 K! gERRON.H 定义错误代码的助记符。9 ?$ Q7 w$ e: {% m: ^3 K* q1 N9 J
FCNTL.H 定义在与open库子程序连接时的符号常量。
. N% K6 Y2 u% p8 }0 q9 AFLOAT.H 包含有关浮点运算的一些参数和函数。" l. u5 L) u" \( J5 W0 v
GRAPHICS.H 说明有关图形功能的各个函数,图形错误代码的常量定义,正对不同驱动程序的各种颜色值,及函数用到的一些特殊结构。
7 l8 s. ~8 v. `: CIO.H 包含低级I/O子程序的结构和说明。
6 u- c+ q7 o; T- ]( E2 o" f/ KLIMIT.H 包含各环境参数、编译时间限制、数的范围等信息。
( N5 V3 r; ^2 _# ]MATH.H 说明数学运算函数,还定了 HUGE VAL 宏, 说明了matherr和matherr子程序用到的特殊结构。/ s( V, s6 G, j L& u* Y/ Q! O0 |
MEM.H 说明一些内存操作函数(其中大多数也在STRING.H 中说明)。 W3 l& Y) Z$ B. j4 d; n$ Y, {
PROCESS.H 说明进程管理的各个函数,spawn…和EXEC …函数的结构说明。
' C6 N! l' U+ A4 QSETJMP.H 定义longjmp和setjmp函数用到的jmp buf类型, 说明这两个函数。
: P& c) J; p p9 j! bSHARE.H 定义文件共享函数的参数。; K6 F: ^3 [' R+ R1 z( {5 e
SIGNAL.H 定义SIG[ZZ(Z] [ZZ)]IGN和SIG[ZZ(Z] [ZZ)]DFL常量,说明rajse和signal两个函数。 ~& w) T# [7 W3 G' a1 t
STDARG.H 定义读函数参数表的宏。(如vprintf,vscarf函数)。
4 V! q* E3 ], x& g/ ZSTDDEF.H 定义一些公共数据类型和宏。: l5 c3 R6 e* W& e
STDIO.H 定义Kernighan和Ritchie在Unix System V 中定义的标准和扩展的类型和宏。还定义标准I/O 预定义流:stdin,stdout和stderr,说明 I/O流子程序。
6 G5 ^8 h( i+ e8 | A# f1 d# Y5 aSTDLIB.H 说明一些常用的子程序:转换子程序、搜索/ 排序子程序等。! B; M0 P1 O% L( i: ^" U" `
STRING.H 说明一些串操作和内存操作函数。$ m# b( O% F. x; l I% f- f
SYS\STAT.H 定义在打开和创建文件时用到的一些符号常量。' {! C0 E# ]9 r3 I7 Q
SYS\TYPES.H 说明ftime函数和timeb结构。8 X* u# {5 x) Y% P, T
SYS\TIME.H 定义时间的类型time[ZZ(Z] [ZZ)]t。' w: q( G! x4 W, _) s6 f( Q
TIME.H 定义时间转换子程序asctime、localtime和gmtime的结构,ctime、 difftime、 gmtime、 localtime和stime用到的类型,并提供这些函数的原型。
& G9 R& H6 Z& z7 {+ JVALUE.H 定义一些重要常量, 包括依赖于机器硬件的和为与Unix System V相兼容而说明的一些常量,包括浮点和双精度值的范围。) p" `7 n8 O0 T( D8 d- M
. i& N: H5 `8 D- ` K, V
<FONT color=#cc0000><B>本章小结</B></FONT>
0 Y d9 D% t8 v2 t5 b" Z0 G/ t: i) m; J" @9 \/ ]
1. C系统把文件当作一个“流”,按字节进行处理。 ' [6 u u* e Q
7 _, I- Q# M8 Y" q: C2. C文件按编码方式分为二进制文件和ASCII文件。: C7 P& l9 v' i) ] \1 u
; J5 `" Q) A# f. \, h% X. v1 d
3. C语言中,用文件指针标识文件,当一个文件被 打开时, 可取得该文件指针。/ T2 c3 j# V% u0 ]/ J, l. V/ h3 M) f
' [( \9 a: T# B: s4. 文件在读写之前必须打开,读写结束必须关闭。
- ]7 _$ g- J" c* Q1 ?" r# [! y. s1 q# o
0 e+ Z% {: \$ B5. 文件可按只读、只写、读写、追加四种操作方式打开,同时还必须指定文件的类型是二进制文件还是文本文件。
4 V" V! _0 \2 | [
3 k" L9 v' j; {" g5 L% r) ?- q0 }6. 文件可按字节,字符串,数据块为单位读写,文件也可按指定的格式进行读写。2 p0 L# Z' Z4 s0 F& ?
4 F( u% e, I4 ^3 e; ^% @7. 文件内部的位置指针可指示当前的读写位置,移动该指针可以对文件实现随机读写。</P> |
|