现在的位置: 首页 > 综合 > 正文

文件操作函数 C语言 (FILE fputc fgetc fputs fgets fscanf fprintf)

2013年09月04日 ⁄ 综合 ⁄ 共 9530字 ⁄ 字号 评论关闭
在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之。中天在线Iz-] Gt t

x&UDU|+r9e)V0一、流式文件操作中天在线1RGA
u#Lm"n#N7z"h

  这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下:
E];D`Q%@0
c4~1I$Z ]@0typedef struct {中天在线H,rE9Ll*qq)ceh
int level; /* fill/empty level of buffer */
2NE3/
c[l*_e0
unsigned flags; /* File status flags */中天在线:IB;o-{F
~gD+hd

char fd; /* File descriptor */
"{.|jy
i9[0
unsigned char hold; /* Ungetc char if no buffer */
O-ra6V9t1_-x#Ibbg0int bsize; /* Buffer size */
-A�j7/Zvd4nx0unsigned char _FAR *buffer; /* Data transfer buffer */中天在线[#hG%LJer
unsigned char _FAR *curp; /* Current active pointer */

k-C2X*F1l1sMRk0
unsigned istemp; /* Temporary file indicator */中天在线7v$mX.rS
short token; /* Used for validity checking */
W9N(lm7vrw0} FILE; /* This is the FILE object */中天在线(B5aw#CT2?!Qn

MH4keO3m�T3U�s)a0  FILE这个结构包含了文件操作的基本属性,对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数见下表 函数 功能中天在线af?*l9s
^W5gw-lY

fopen() 打开流
;Z9@?F"z+i0fclose() 关闭流中天在线"jv"~{B0^wE
fputc() 写一个字符到流中
!N!b%RBx0fgetc() 从流中读一个字符中天在线)n7i2H5/O
fseek() 在流中定位到指定的字符
[p*Jsd gzt7j0fputs() 写字符串到流
-JKK[
P%q-p0
fgets() 从流中读一行或指定个字符中天在线x6Um j/tl!k
fprintf() 按格式输出到流
+|$AKN3_]0fscanf() 从流中按格式读取
,vT LH�w
|0
feof() 到达文件尾时返回真值
AxDe&W0ferror() 发生错误时返回其值
*Ku5lgm/f0rewind() 复位文件定位器到文件开始处中天在线-yK:M3H.R ge.I!h[)?a
remove() 删除文件中天在线
q(_FY`&Q:Q

fread() 从流中读指定个数的字符中天在线)j(_+_2@||/b
fwrite() 向流中写指定个数的字符中天在线U{Y,G nesZ
tmpfile() 生成一个临时文件流
R+L:fq)b0tmpnam() 生成一个唯一的文件名中天在线s[kLqeN:O
|v4r

%R|t"j/Ya;]v0中天在线 K~0s9F$B5^
~

  下面就介绍一下这些函数中天在线t1@:wC?
中天在线"|�H5`*Vd1j/~
1.fopen()中天在线8Z%^AL6|Bi
  fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能中天在线u#HSR0z.lH.xE

ZV(H[Qld0为使用而打开一个流中天在线o{E#a6^?
把一个文件和此流相连接中天在线Pe
B6I0W/N

给此流返回一个FILR指针
'_-_yXR0m'~0参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下表
1i/y,A
T4mHY0

9Q:g'xG["v]0字符串 含义中天在线4{[~hK?.D'bZ{
P

"r" 以只读方式打开文件中天在线kj�wKK8bj
"w" 以只写方式打开文件
x`}#K�B6k*u0"a" 以追加方式打开文件中天在线z9ZH
Bk

"r+" 以读/写方式打开文件,如无文件出错中天在线u@X&r?Q
"w+" 以读/写方式打开文件,如无文件生成新文件中天在线'G"yI'G&]6ys#K
中天在线 K7}kD:}dT
 
 一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'n',而二进制模式认为它是两个字符0x0D,0x0A;
如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。
!`s"]7NU9J0
:A'O3iJ3obl]/0  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。中天在线@?N�P0Z_!hZ

{`UmYf Q0  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。
"}O/eu,M:C0

hTPL?U6[0
  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL。中天在线B-c k$y*TMV0I'wq/J3Lx
中天在线3jI-I/Cj^
例:
sYV&Ip/Ba0中天在线JLYd dT
  FILE *fp;中天在线K
^n.ZVVt

  if(fp=fopen("123.456","wb"))中天在线l4x*Wr#D5Ub/.l:wk+v
    puts("打开文件成功");中天在线TKl ]r6S2ki
  else中天在线u�rJ+UOR
    puts("打开文件成败");
U;vr8MY}G0
/F%l@4/f:m4s @I02.fclose()
1F#Y*NT`0  fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。中天在线;BZGvg/ i
中天在线
ugn:yv1tak
W9XctL

  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的毛病。中天在线'cL){[#J'}
中天在线-M)L0w gv U
I&K{&b,v$E

例:fclose(fp);中天在线 uIf.k g`&D

/8v+t-@?5vzR03.fputc()
a;S2r'q s|0  向流写一个字符,原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。
s(j'h8Y)PC�M7As0中天在线:/,u){`#Eou
例:fputc('X',fp);
9LuyJvF+S5o0中天在线/j2ZT!a%P&S
4.fgetc()中天在线m
l'E3D5C{}go

  从流中读一个字符,原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。中天在线(DOzQY'JI

9QJ,aS/T8o0例:char ch1=fgetc(fp);
![0m:]a&ojz
SK'Z0
中天在线7v(eJg+x
?�Bs

5. fseek()
$a#p{rW+xj0^t4@/]0Q0  此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是中天在线e3UJs3L"F

.v
~y|/A0
符号常量 值 基准位置
^8`PK&K0SEEK_SET 0 文件开头中天在线 tu3L+|
ygdr L D9]

SEEK_CUR 1 当前读写的位置
$m@)IE!HbS%f0SEEK_END 2 文件尾部
N w7d*BH2N0?m0
yi;n-@O/D:QW0例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)
*W:|1z,ohgH6a*^0中天在线"pMbY$_ UU(n)r
  fseek(fp,0L,2);//把读写位置移动到文件尾中天在线(j['Vt)K0t9L
中天在线/i5FS5A%}6h/y'd
6.fputs()中天在线*H,z3`$l(W`#U
  写一个字符串到流中,原型int fputs(const char *s, FILE *stream);中天在线c#`1k"E0^"cQ|7dc)T4n

2g9v$K5ZQO F
L0
例:fputs("I Love You",fp);中天在线NM+q.|"bn]9{

)FNA2D/_07.fgets()中天在线$nFVdC N
Y

  从流中读一行或指定个字符,原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。
4GE;J9]c't0中天在线v
]�D.O@2d1y!@

例:如果一个文件的当前位置的文本如下
$T%a!lT7~T8O+S5i1f0中天在线TaCoB3}y,krb;b
Love ,I Have
l}2Q6v,Ws0
b$EY.HEa6K9_s3g0But ........
.C/P`h}�p0
w'R2{jC/yU;a8T![0如果用中天在线3F$t)}%iP#D._'SQ
H_

中天在线7]R6qY)QM'@(?h2R0w
  fgets(str1,4,file1);中天在线-zU$KyA7zz^

8Zt7@h8Xt_t0则执行后str1="Lov",读取了4-1=3个字符,而如果用中天在线Ed#PHz
N
|

'h$I)po;eVVx�F0  fgets(str1,23,file1);中天在线)`p9lmX�X5o,|
中天在线"Cq
I�W,C:f?Rx

则执行str="Love ,I Have",读取了一行(不包括行尾的'n')。
_5F?~ mK0中天在线.R&TX0e5ik
x9?eT

8.fprintf()中天在线{+`{:/t1n%i+cYC
  按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了
SOC7G#c8fN0中天在线rw$s|&A0F
例:fprintf(fp,"%2d%s",4,"Hahaha");中天在线3p1OY�u
OB!lM

6w Lt-P)W ]s+eJ09.fscanf()
s
@bTW0
  从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, ...]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。中天在线mz,w:t+X6h5N
中天在线;o@sLTU'Z
例:fscanf(fp,"%d%d" ,&x,&y);
"nV(V:~)w`w0中天在线/G$~W-O6g#{
10.feof()中天在线:]lQKZ-ZV
  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream);中天在线&Ce$t5X FNv
中天在线iQPPt
例:if(feof(fp))printf("已到文件尾");
#kBq;D*E
S4{0
中天在线Fd}7/JV|(H`B
t

11.ferror()

i-O%n$t5MHxjcPP0
  原型是int ferror(FILE *stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是void clearerr(FILE *stream);
0J G} [G1R^"T-|0
|GoX$g m0例:printf("%d",ferror(fp));中天在线7gU9DBx[z
中天在线S}+Z]t
12.rewind()中天在线Yg*PC]
  把当前的读写位置回到文件开始,原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);
N#dQ|k2G
u@fJr0
中天在线&`jv+D%H"Ov.oE
例:rewind(fp);
5Zd"w,Lb_,[0
iX;k6I2Vu3zDU012.remove()中天在线:g%}gnkM"iv2^
  删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。中天在线;nN].M0O3Y(MH
中天在线:H1]a8Rdh#A
例:remove("c:io.sys");
Z1L[u4q0
X4agQ(h013.fread()中天在线&o6]jWW5H2V?ds
 
 从流中读指定个数的字符,原型是size_t fread(void *ptr, size_t size, size_t n, FILE
*stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int
*等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。中天在线z:`qa1LN
中天在线O?q!U/c
例:
ud;u.g5_0中天在线-Jw;n F(c
  char x[4230];中天在线 _w&`Lge
  FILE *file1=fopen("c:msdos.sys","r");
Uuu,k7dk
d0
  fread(x,200,12 ,file1);//共读取200*12=2400个字节中天在线
/O7N3fdkg

中天在线;Zp%t/[SE
14.fwrite()中天在线X)sV4gyI2i+{
 
 与fread对应,向流中写指定的数据,原型是size_t fwrite(const void *ptr, size_t size,
size_t n, FILE *stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int
*等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。中天在线]#y0J!wY9w5[G
nb

中天在线f4B1m`_pD
例:
l?7HEY)M1l-TF0
@'z6ZY$RLR}1N0  char x[]="I Love You";
y;Bh8@%L.M0  fwire(x, 6,12,fp);//写入6*12=72字节中天在线:YU8XhX+D�vM:c

_C&X ^1qB.b0  将把"I Love"写到流fp中12次,共72字节
|
Wut.S7h
I�Q0
中天在线e.|)]"^M1c&e
15.tmpfile()中天在线5a%yvKJdM(A|_
  其原型是FILE *tmpfile(void); 生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。
&KsOH|'u0
@
WdN#V1]0
例:FILE *fp=tmpfile();中天在线i Do1QBb#E}1}
中天在线-nf^�m*['PVm
16.tmpnam();
I}(by6o
E!op"k0
  其原型为char *tmpnam(char *s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。
m)_gttQ0
9z)oh}-c
Y,]W0
例:tmpnam(str1);
/T"v6p@;O Q3}2LA0
FEI
r,dTi;ez
bd0
二、直接I/O文件操作
WT!s3l?!q0 
 这是C提供的另一种文件操作,它是通过直接存/取文件来完成对文件的处理,而上篇所说流式文件操作是通过缓冲区来进行;流式文件操作是围绕一个FILE
指针来进行,而此类文件操作是围绕一个文件的“句柄”来进行,什么是句柄呢?它是一个整数,是系统用来标识一个文件(在WINDOWS中,句柄的概念扩展
到所有设备资源的标识)的唯一的记号。此类文件操作常用的函数如下表,这些函数及其所用的一些符号在io.h和fcntl.h中定义,在使用时要加入相应
的头文件。中天在线,]E.O,]*a

3n5/uc7C4O.J0函数 说明中天在线OE'tny1{X
J

1.open()
X�v,iv)h"Gs!N0 
 打开一个文件并返回它的句柄,如果失败,将返回一个小于0的值,原型是int open(const char *path, int access
[, unsigned mode]);
参数path是要打开的文件名,access是打开的模式,mode是可选项。表示文件的属性,主要用于UNIX系统中,在DOS/WINDOWS这个参
数没有意义。其中文件的打开模式如下表。
f0zf.haC0中天在线 xJ.H~EY
符号 含义 符号 含义 符号 含义
L!s0A�|3vp ~#_T0O_RDONLY 只读方式 O_WRONLY 只写方式 O_RDWR 读/写方式
i*}$GH6C)mt9i0O_NDELAY 用于UNIX系统 O_APPEND 追加方式 O_CREAT 如果文件不存在就创建
)mf'ltV9m0O_TRUNC 把文件长度截为0 O_EXCL 和O_CREAT连用,如果文件存在返回错误 O_BINARY 二进制方式
PwA2d7Su$G
b&y{+Q:n0
O_TEXT 文本方式中天在线.M"r�od%Byv| s
中天在线*r'll2hWNq'V
  对于多个要求,可以用"|"运算符来连接,如O_APPEND|O_TEXT表示以文本模式和追加方式打开文件。中天在线/hkd`8R t

&d&uE"_N5V;z0例:int handle=open("c:msdos.sys",O_BINARY|O_CREAT|O_WRITE)中天在线y:U@K.D+D /zU
中天在线H7^l%sT
2.close()中天在线3PT*x0J:g3f+C,G
  关闭一个句柄,原型是int close(int handle);如果成功返回0中天在线f_4V(|'~KX9{
中天在线 uz%{v7Yl} ?%V?
例:close(handle)
6|"@{(J,b;e X6[:f0
(@]2e'v
b+E-{0
3.lseek()中天在线Q)e;r[i
 
 定位到指定的位置,原型是:long lseek(int handle, long offset, int
fromwhere);参数offset是移动的量,fromwhere是移动的基准位置,取值和前面讲的fseek()一样,SEEK_SET:文件首
部;SEEK_CUR:文件当前位置;SEEK_END:文件尾。此函数返回执行后文件新的存取位置。中天在线5?z/JCdi$N

%y.YY ax3L}V0例:
k/yF,eLz0中天在线)m;mBFI�`
  lseek(handle,-1234L,SEEK_CUR);//把存取位置从当前位置向前移动1234个字节。中天在线7eA0hB?
  x=lseek(hnd1,0L,SEEK_END);//把存取位置移动到文件尾,x=文件尾的位置即文件长度
8Z8^G6/!G0
,v,E(f*Y%xNx04.read()中天在线QF5Ia!O+RErI6a+_
  从文件读取一块,原型是int read(int handle, void *buf, unsigned len);参数buf保存读出的数据,len是读取的字节。函数返回实际读出的字节。
3Qs�H5Ks/wN&d+f1z0
ntnPj@0例:char x[200];read(hnd1,x,200);中天在线_sn&bGn�Y
中天在线'mf'l7F"G`5j)aZ
5.write()
0Am ct]8Y.L0  写一块数据到文件中,原型是int write(int handle, void *buf, unsigned len);参数的含义同read(),返回实际写入的字节。中天在线s8pn�M N%]
中天在线,|c8u-JMu/Z
例:char x[]="I Love You";write(handle,x,strlen(x));
$?U+OEPn'H0
2EQ#qPxQ4is5eE07.eof()中天在线H HQ BT|�c.~
  类似feof(),测试文件是否结束,是返回1,否则返回0;原型是:int eof(int handle);中天在线b8zp
jO"W*Ulvy)Z

5S8o:L#P
H0
例:while(!eof(handle1)){……};中天在线e
tb!N$a|$wg

Uw;z@Pd08.filelength()
Abk$S'PM6_sd0  返回文件长度,原型是long filelength(int handle);相当于lseek(handle,0L,SEEK_END)
例:long x=filelength(handle);中天在线2n&}(oDtXct
中天在线O-`%_,@Vg8R
9.rename()
W6Mpz!yM XE0h0  重命名文件,原型是int rename(const char *oldname, const char *newname); 参数oldname是旧文件名,newname是新文件名。成功返回0
%W z h(R-BVQ0中天在线C;km;~MX`?.o
例:rename("c:config.sys","c:config.w40");中天在线X-kh6Bm0j~
中天在线-J�u[(p,j.k
10.chsize();
o2?%?_ aQ'}+Rs0  改变文件长度,原型是int chsize(int handle, long size);参数size表示文件新的长度,成功返回0,否则返回-1,如果指定的长度小于文件长度,则文件被截短;如果指定的长度大于文件长度,则在文件后面补''。
*XyD e}0
:R!|6y,py{l'D0例:chsize(handle,0x12345);中天在线/dq!|E$T"}G
中天在线2[9NW-L
iI

中天在线6W:fn2go
--------------------------------------------------------------------------------中天在线�PsSV-RR[j0t*c

$^n!_"GG7BD%_Qm0 
 如果熟悉汇编可能会发现这种方式和汇编语言的DOS功能调用句柄式文件操作很像,比如open()就像DOS服务的3CH号功能调用,其实这种操作还有
两种类型的函数就是直接用DOS功能来完成的,如_open(),_dos_open()等等。有兴趣可自已查询BCB的帮助。
-dO4k l#[0
#tM4q`2s"SAw'j0U0  同流式文件操作相同,这种也提供了Unicode字符操作的函数,如_wopen()等等,用于9X/NT下的宽字符编程,有兴趣可自已查询BCB的帮助。中天在线8NP MD)?Bl

/*F8|c&{ i0  另外,此种操作还有lock(),unlock(),locking()等用于多用户操作的函数,但在BCB中用得并不多,我就不介绍了,但如果要用C来写CGI,这些就必要的常识了,如果你有这方面的要求,那就得自已好好看帮助了。

抱歉!评论已关闭.