Linux⽂件编程—fopen函数
1.2  ⽂件的输⼊输出函数
键盘、显⽰器、打印机、磁盘驱动器等逻辑设备, 其输⼊输出都可以通过⽂件管理的⽅法来完成。⽽在编程时使⽤最多的要算是磁盘⽂件, 因此本节主要以磁盘⽂件为主, 详细介绍Turbo C2.0提供的⽂件操作函数, 当然这些对⽂件的操作函数也适合于⾮磁盘⽂件的情况。
另外, Turbo C2.0提供了两类关于⽂件的函数。⼀类称做标准⽂件函数也称缓冲型⽂件函数, 这是ANSI标准定义的函数; 另⼀类叫⾮标准⽂件函数, 也称⾮缓冲型⽂件函数。这类函数最早公⽤于UNIX操作系统, 但现在MS-DOS3.0以上版本的操作系统也可以使⽤。下⾯分别进⾏介绍。
1.2.1标准⽂件函数
标准⽂件函数主要包括⽂件的打开、关闭、读和写等函数。不象BASIC 、 FORTRAN语⽅有顺序⽂件和随机⽂件之分,  在打开时就应按不同的⽅式确定。Turbo C2.0并不区分这两种⽂件, 但提供了两组函数, 即顺序读写函数和随机读写函数。
⼀、⽂件的打开和关闭
任何⼀个⽂件在使⽤之前和使⽤之后, 必须要进⾏打开和关闭, 这是因为操作系统对于同时打开的⽂件数⽬是有限制的, DOS操作系统中,    可以在DEVICE .SYS中定义允许同时打开的⽂件数n(⽤files=n定义)。其中n 为可同时打开的⽂件数, ⼀般n<=20。因此在使⽤⽂件前应打开⽂件, 才可对其中的信息进⾏存取。⽤完之后需要关闭, 否则将会出现⼀些意想不到的错误。Turbo C2.0提供了打开和关闭⽂件的函数。
1. fopen()函数
fopen函数⽤于打开⽂件, 其调⽤格式为:
FILE *fopen(char *filename, *type);
在介绍这个函数之;前, 先了解⼀下下⾯的知识。
(1) 流(stream)和⽂件(file)
流和⽂件在Turbo C2.0中是有区别的, Turbo C2.0为编程者和被访问的设备之间提供了⼀层抽象的东西, 称之为"流", ⽽将具体的实际设备叫做⽂件。流是⼀个逻辑设备, 具有相同的⾏为。因此, ⽤来进⾏磁盘⽂件写的函数也同样可以⽤来进⾏打印机的写⼊。在Turbo C2.0中有两种性质的流:  ⽂字流( text stream)和⼆进制(binary stream)。对磁盘来说就是⽂本⽂件和⼆进制⽂件。本软件为了便于让读者易
理解Turbo C2.0语⾔⽽没有对流和⽂件作特别区分。    (2) ⽂件指针FILE
实际上FILE是⼀个新的数据类型。它是Turbo C2.0的基本数据类型的集合, 称之为结构指针。有关结构的概念将在第四节中详细介绍, 这⾥只要将FILE理解为⼀个包括了⽂件管理有关信息的数据结构, 即在打开⽂件时必须先定义⼀个⽂件指针。
(3) 以后介绍的函数调⽤格式将直接写出形式参数的数据类型和函数返回值的数据类型。例如: 上⾯打开⽂件的函数, 返回⼀个⽂件指针, 其中形式参数有两个, 均为字符型变量(字符串数组或字符串指针)。本软件不再对函数的调⽤格式作详细说明。
现在再来看打开⽂件函数的⽤法。
fopen()函数中第⼀个形式参数表⽰⽂件名, 可以包含路径和⽂件名两部分。如:
"B:TEST.DAT"
"C://TC//TEST.DAT"
如果将路径写成"C:/T C/T EST.DAT"是不正确的, 这⼀点要特别注意。
第⼆个形式参数表⽰打开⽂件的类型。关于⽂件类型的规定参见下表。
表⽂件操作类型
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
字符含义
────────────────────────────
"r"打开⽂字⽂件只读
"w"创建⽂字⽂件只写
"a"增补, 如果⽂件不存在则创建⼀个
"r+"打开⼀个⽂字⽂件读/写
"w+"创建⼀个⽂字⽂件读/写
"a+"打开或创建⼀个⽂件增补
"b"⼆进制⽂件(可以和上⾯每⼀项合⽤)
"t"⽂这⽂件(默认项)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
如果要打开⼀个CCDOS⼦⽬录中, ⽂件名为CLIB的⼆进制⽂件, 可写成:
fopen("c://ccdos//clib", "rb");
如果成功的打开⼀个⽂件, fopen()函数返回⽂件指针,  否则返回空指针 (NULL)。由此可判断⽂件打开是否成功。
2. fclose()函数
fclose()函数⽤来关闭⼀个由fopen()函数打开的⽂件 , 其调⽤格式为:
int fclose(FILE *stream);
该函数返回⼀个整型数。当⽂件关闭成功时, 返回0, 否则返回⼀个⾮零值。可以根据函数的返回值判断⽂件是否关闭成功。
例10:
例10:
#iclude<stdio.h>
main()
{
FILE *fp;                /*定义⼀个⽂件指针*/
int i;
fp=fopen("CLIB", "rb");  /*打开当前⽬录名为CLIB的⽂件只读*/
if(fp==NULL)            /*判断⽂件是否打开成功*/
puts("File open error");/*提⽰打开不成功*/
i=fclose(fp);            /*关闭打开的⽂件*/
if(i==0)                /*判断⽂件是否关闭成功*/
printf("O,K");        /*提⽰关闭成功*/
else
puts("File close error");/*提⽰关闭不成功*/
}
⼆、有关⽂件操作的函数
本节所讲的⽂件读写函数均是指顺序读写, 即读写了⼀条信息后, 指针⾃动加1。下⾯分别介绍写操作函数和读操作函数。
1.⽂件的顺序写函数
fprintf()、fputs()和fputc()函数
函数fprintf()、fputs()和fputc()均为⽂件的顺序写操作函数,  其调⽤格式如下:
int fprintf(FILE *stream, char *format, <variable-list>);
int fputs(char *string, FILE *steam);
int fputc(int ch, FILE *steam);
上述三个函数的返回值均为整型量。fprintf() 函数的返回值为实际写⼊⽂件中的字罕个数(字节数)。如果写错误, 则返回⼀个负数, fputs()函数返回0时表明将string指针所指的字符串写⼊⽂件中的操作成功, 返回⾮0时,  表明写操作失败。fputc()函数返回⼀个向⽂件所写字符的值, 此时写操作成功,  否则返回EOF(⽂件结束结束其值为-1, 在stdio.h中定义)表⽰写操作错误。
fprintf( ) 函数中格式化的规定与printf( ) 函数相同,  所不同的只是 fprintf()函数是向⽂件中写⼊。⽽printf()是向屏幕输出。
下⾯介绍⼀个例⼦, 运⾏后产后⼀个test.dat的⽂件。
例11:
#include<stdio.h>
main()
{
char *s="That's good news";  /*定义字符串指针并初始化*/
int i=617;                    /*定义整型变量并初始化*/
FILE *fp;                    /*定义⽂件指针*/
fp=fopne("test.dat", "w");    /*建⽴⼀个⽂字⽂件只写*/
fputs("Your score of TOEFLis", fp);/*向所建⽂件写⼊⼀串字符*/
fputc(':', fp);              /*向所建⽂件写冒号:*/
fprintf(fp, "%d/n", i);      /*向所建⽂件写⼀整型数*/
fprintf(fp, "%s", s);        /*向所建⽂件写⼀字符串*/
fclose(fp);                  /*关闭⽂件*/
}
⽤DOS的TYPE命令显⽰TEST.DAT的内容如下所⽰:
屏幕显⽰
Your score of TOEFL is: 617
That's good news
2.⽂件的顺序读操作函数
fscanf()、fgets()和fgetc()函数
函数fscanf()、fgets()和fgetc()均为⽂件的顺序读操作函数, 其调⽤格式如下:
int fscanf(FILE *stream, char *format, <address-list>);
char fgets(char *string, int n, FILE *steam);
int fgetc(FILE *steam);
fscanf()函数的⽤法与scanf()函数相似,  只是它是从⽂件中读到信息。 fscanf()函数的返回值为EOF(即-1), 表明读错误, 否则读数据成功。fgets()函数从⽂
fscanf()函数的⽤法与scanf()函数相似,  只是它是从⽂件中读到信息。 fscanf()函数的返回值为EOF(即-1), 表明读错误, 否则读数据成功。fgets()函数从⽂件中读取⾄多n-1个字符(n⽤来指定字符数),
并把它们放⼊string指向的字符串中, 在读⼊之后⾃动向字符串未尾加⼀个空字符, 读成功返回string指针, 失败返回⼀个空指针。fgetc()函数返回⽂件当前位置的⼀个字符,  读错误时返回EOF。
下⾯程序读取例11产⽣的test.dat⽂件, 并将读出的结果显⽰在屏幕上。
例12
#include<stdio.h>
main()
{
char *s, m[20];
int i;
FILE  *fp;
fp=fopen("test.dat", "r");    /*打开⽂字⽂件只读*/
fgets(s, 24, fp);            /*从⽂件中读取23个字符*/
printf("%s", s);              /*输出所读的字符串*/
fscanf(fp, "%d", &i);        /*读取整型数*/
printf("%d", i);              /*输出所读整型数*/
putchar(fgetc(fp));          /*读取⼀个字符同时输出*/
fgets(m, 17, fp);            /*读取16个字符*/
puts(m);                      /*输出所读字符串*/
fclose(fp);                  /*关闭⽂件*/
getch();                      /*等待任⼀键*/
}
运⾏后屏幕显⽰:
Your score of TOEFL is: 617
That's good news
如果将上例中fscanf(fp, "%d", &i)改为fscanf(fp, "%s", m),  再将其后的输出语句改为printf("%s", m), 则可得出同样的结果。由此可见Turbo C2. 0中只要是读⽂字⽂件, 则不论是字符还是数字都将按其ASCII值处理。另外还要说明的⼀点就是fscanf()函数读到空⽩符时, 便⾃动结束, 在使⽤时要特别注意。
3.⽂件的随机读写
有时⽤户想直接读取⽂件中间某处的信息, 若⽤⽂件的顺序读写必须从⽂件头开始直到要求的⽂件位置再读, 这显然不⽅便。Turbo C2.0提供了⼀组⽂件的随机读写函数, 即可以将⽂件位置指针定位在所要求读写的地⽅直接读写。
⽂件的随机读写函数如下:
int fseek (FILE *stream, long offset, int fromwhere);
int fread(void *buf, int size, int count, FILE *stream);
int fwrite(void *buf, int size, int count, FILE *stream);
long ftell(FILE *stream);
fseek()函数的作⽤是将⽂件的位置指针设置到从fromwhere开始的第offset 字节的位置上, 其中fromwhere是下列⼏个宏定义之⼀:
⽂件位置指针起始计算位置fromwhere ━━━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数数值含义───────────────────────────
SEEK_SET0从⽂件开头
SEEK_CUR1从⽂件指针的现⾏位置
SEEK_END2从⽂件末尾━━━━━━━━━━━━━━━━━━━━━━━━━━━
offset是指⽂件位置指针从指定开始位置(fromwhere指出的位置)跳过的字节数。它是⼀个长整型量, 以⽀持⼤于64K字节的⽂件。fseek()函数⼀般⽤于对⼆进制⽂件进⾏操作。
当fseek()函数返回0时表明操作成功, 返回⾮0表⽰失败。
下⾯程序从⼆进制⽂件test_b.dat中读取第8个字节。
例13:
#include<stdio.h>
main()
{
FILE *fp;
if((fp=fopen("test_b.dat", "rb"))==NULL)
{
printf("Can't open file");
exit(1);
}
}
fseek(fp, 8.1, SEEK_SET);
fgetc(fp);
fclose(fp);
}
fread()函数是从⽂件中读count个字段, 每个字段长度为size个字节, 并把它们存放到buf指针所指的缓冲器中。
fwrite()函数是把buf指针所指的缓冲器中, 长度为size个字节的count个字段写到stream指向的⽂件中去。
随着读和写字节数的增⼤, ⽂件位置指⽰器也增⼤, 读多少个字节, ⽂件位置指⽰器相应也跳过多少个字节。读写完毕函数返回所读和所写的字段个数。
ftell()函数返回⽂件位置指⽰器的当前值,  这个值是指⽰器从⽂件头开始算起的字节数, 返回的数为长整型数, 当返回-1时, 表明出现错误。
下⾯程序把⼀个浮点数组以⼆进制⽅式写⼊⽂件test_b.dat中。
例14:
#include <stdio.h>
main()
{
float f[6]={3.2, -4.34, 25.04, 0.1, 50.56, 80.5};
/*定义浮点数组并初始化*/
int i;
FILE *fp;
fp=fopen("test_b.dat", "wb"); /*创建⼀个⼆进制⽂件只写*/
fwrite(f, sizeof(float), 6, fp);/*将6个浮点数写⼊⽂件中*/
fclose(fp);                  /*关闭⽂件*/
}
下⾯例⼦从test_b.dat⽂件中读100个整型数, 并把它们放到dat数组中。
例15:
#include <stdio.h>
main()
{
FILE *fp;
int dat[100];
fp=fopen("test_b.dat", "rb");/*打开⼀个⼆进制⽂件只读*/
if(fread(dat, sizeof(int), 100, fp)!=100)
/*判断是否读了100个数*/
{
if(feof(fp))
printf("End of file"); /*不到100个数⽂件结束*/
else
printf("Read error");  /*读数错误*/
fclose(fp);                  /*关闭⽂件*/
}
注意:
当⽤标准⽂件函数对⽂件进⾏读写操作时, ⾸先将所读写的内容放进缓冲区, 即写函数只对输出缓冲区进⾏操作, 读函数只对输⼊缓冲区进⾏操作。例如向⼀个⽂件写⼊内容, 所写的内容将⾸先放在输出缓冲区中, 直到输出缓冲区存满或使⽤fclose()函数关闭⽂件时, 缓冲区的内容才会写⼊⽂件中。若⽆fclose() 函数, 则不会向⽂件中存⼊所写的内容或写⼊的⽂件内容不全。有⼀个对缓冲区进⾏刷新的函数, 即fflush(), 其调⽤格式为:
int fflush(FILE *stream);
该函数将输出缓冲区的内容实际写⼊⽂件中, ⽽将输⼊缓冲区的内容清除掉。
4. feof()和rewind()函数
这两个函数的调⽤格式为:
int feof(FILE *stream);
int rewind(FILE *stream);
feof()函数检测⽂件位置指⽰器是否到达了⽂件结尾,  若是则返回⼀个⾮0值, 否则返回0。这个函数对⼆进制⽂件操作特别有⽤, 因为⼆进制⽂件中,  ⽂件结尾标志EOF也是⼀个合法的⼆进制数,  只简单的检查读⼊字符的值来判断⽂件是否结束是不⾏的。如果那样的话, 可能会造成⽂件未结尾⽽被认为结尾, 所以就必须有feof()函数。
下⾯的这条语句是常⽤的判断⽂件是否结束的⽅法。
while(!feof(fp))
fgetc(fp);
fgetc(fp);
while为循环语句, 将在下⾯介绍。
rewind()函数⽤于把⽂件位置指⽰器移到⽂件的起点处, 成功时返回0,  否则, 返回⾮0值。
1.2.2⾮标准⽂件函数
这类函数最早⽤于UNIX操作系统, ANSI标准未定义,  但有时也经常⽤到, DOS 3.0以上版本⽀持这些函数。它们的头⽂件为io.h。
⼀、⽂件的打开和关闭
1. open()函数
open()函数的作⽤是打开⽂件, 其调⽤格式为:
int open(char *filename, int access);
该函数表⽰按access的要求打开名为filename的⽂件, 返回值为⽂件描述字, 其中access有两部分内容: 基本模式和修饰符, 两者⽤" "("或")⽅式连接。修饰
符可以有多个, 但基本模式只能有⼀个。access的规定如表3-2。
表3-2  access的规定━━━━━━━━━━━━━━━━━━━━━━━━━━━━基本模式含义修饰符含义──────────────────────────── O_RDONLY    只读  O_APPEND  ⽂件指针指向末尾 O_WRONLY    只写  O_CREAT    ⽂件不存在时创建⽂件,
属性按基本模式属性 O_RDWR      读写  O_TRUNC    若⽂件存在, 将其长度
缩为0, 属性不变
ascii文字是啥O_BINARY  打开⼀个⼆进制⽂件
O_TEXT    打开⼀个⽂字⽂件━━━━━━━━━━━━━━━━━━━━━━━━━━━━
open()函数打开成功, 返回值就是⽂件描述字的值(⾮负值), 否则返回-1。
2. close()函数
close()函数的作⽤是关闭由open()函数打开的⽂件, 其调⽤格式为:
int close(int handle);
该函数关闭⽂件描述字handle相连的⽂件。
⼆、读写函数
1. read()函数
read()函数的调⽤格式为:
int read(int handle, void *buf, int count);
read()函数从handle(⽂件描述字)相连的⽂件中, 读取count个字节放到buf 所指的缓冲区中, 返回值为实际所读字节数, 返回-1表⽰出错。返回0表⽰⽂件结束。
2. write()函数
write()函数的调⽤格式为:
int write(int handle, void *buf, int count);
write()函数把count个字节从buf指向的缓冲区写⼊与handle相连的⽂件中, 返回值为实际写⼊的字节数。
三、随机定位函数
1. lseek()函数
lseek()函数的调⽤格式为:
int lseek(int handle, long offset, int fromwhere);
该函数对与handle相连的⽂件位置指针进⾏定位, 功能和⽤法与fseek() 函数相同。
2. tell()函数
tell()函数的调⽤格式为:
long tell(int handle);
该函数返回与handle相连的⽂件现⽣位置指针, 功能和⽤法与ftell()相同。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。