c语⾔⽂件输⼊输出函数详解
C语⾔⽂件输⼊输出函数详解
1. 需要了解的概念
需要理解的知识点包括:数据流、缓冲区、⽂件类型、⽂件存取⽅式
1.1 数据流:
指程序与数据的交互是以流的形式进⾏的。进⾏C语⾔⽂件的存取时,都会先进⾏“打开⽂件”操作,这个操作就是在打开数据流,⽽“关闭⽂件”操作就是关闭数据流。
1.2 缓冲区(Buffer):
指在程序执⾏时,所提供的额外内存,可⽤来暂时存放做准备执⾏的数据。它的设置是为了提⾼存取效率,因为内存的存取速度⽐磁盘驱动器快得多。
C语⾔中带缓冲区的⽂件处理:
C语⾔的⽂件处理功能依据系统是否设置“缓冲区”分为两种:⼀种是设置缓冲区,另⼀种是不设置缓冲区。
由于不设置缓冲区的⽂件处理⽅式,必须使⽤较低级的I/O函数(包含在头⽂件io.h和fcntl.h中)来直接对磁盘存取,这种⽅式的存取速度慢,并且由于不是C的标准函数,跨平台操作时容易出问题。下⾯只介绍第⼀种处理⽅式,即设置缓冲区的⽂件处理⽅式:
当使⽤标准I/O函数(包含在头⽂件stdio.h中)时,系统会⾃动设置缓冲区,并通过数据流来读写⽂件。当进⾏⽂件读取时,不会直接对磁盘进⾏读取,⽽是先打开数据流,将磁盘上的⽂件信息拷贝到缓冲区内,然后程序再从缓冲区中读取所需数据,如下图所⽰:
事实上,当写⼊⽂件时,并不会马上写⼊磁盘中,⽽是先写⼊缓冲区,只有在缓冲区已满或“关闭⽂件”时,才会将数据写⼊磁盘,如下图所⽰。
1.3 ⽂件类型:
分为⽂本⽂件和⼆进制⽂件两种。
⽂本⽂件是以字符编码的⽅式进⾏保存的。⼆进制⽂件将内存中数据原封不⾄⽂件中,适⽤于⾮字符为主的数据。如果以记事本打开,只会看到⼀堆乱码。
其实,除了⽂本⽂件外,所有的数据都可以算是⼆进制⽂件。⼆进制⽂件的优点在于存取速度快,占⽤空间⼩,以及可随机存取数据。
1.4 ⽂件存取⽅式:
包括顺序存取⽅式和随机存取⽅式两种。
顺序读取也就是从上往下,⼀笔⼀笔读取⽂件的内容。保存数据时,将数据附加在⽂件的末尾。这种存取⽅式常⽤于⽂本⽂件,⽽被存取的⽂件则称为顺序⽂件。
随机存取⽅式多半以⼆进制⽂件为主。它会以⼀个完整的单位来进⾏数据的读取和写⼊,通常以结构为单位。
2. ⽂本⽂件操作
C语⾔中主要通过标准I/O函数来对⽂本⽂件进⾏处理。相关的操作包括打开、读写、关闭与设置缓冲区。
相关的存取函数有:fopen(), fclose(), fgetc(), fputc(), fgets(),fputs(), fprintf(), fscanf()等。
2.1打开⽂件
函数原型为:_CRTIMP FILE * __cdecl fopen(constchar *, const char *);
第⼀参数为⽂件名,第⼆个参数为打开模式。
打开成功,fopen返回⼀个结构指针地址,否则返回⼀个NULL。如果没有指定⽂件路径,则默认为当前⼯作⽬录。如:
FILE *fp;
fp = fopen("c:\\temp\\", "r") //由于反斜杠\是控制字符,所以必须再加⼀个反斜杠
使⽤fopen()函数打开的⽂件会先将⽂件复制到缓冲区。注意:所下达的读取或写⼊动作,都是针对缓冲区进⾏存取⽽不是磁盘,只有当使⽤fclose()函数关闭⽂件时,缓冲区中的数据才会写⼊磁盘。
谈⽂件打开模式
打开⽂本⽂件:
"r":只能从⽂件中读数据,该⽂件必须先存在,否则打开失败
"w":只能向⽂件写数据,若指定的⽂件不存在则创建它,如果存在则先删除它再重建⼀个新⽂件
"a":向⽂件增加新数据(不删除原有数据),若⽂件不存在则打开失败,打开时位置指针移到⽂件末尾
"r+":可读/写数据,该⽂件必须先存在,否则打开失败
"w+":可读/写数据,⽤该模式打开新建⼀个⽂件,先向该⽂件写数据,然后可读取该⽂件中的数据
"a+":可读/写数据,原来的⽂件不被删去,位置指针移到⽂件末尾
打开⼆进制⽂件的模式与打开⽂本⽂件的含义是⼀样的,不同的是模式名称⾥⾯多⼀个字母'b’,以表⽰以⼆进制形式打开⽂件。
2.2 关闭⽂件
函数原型为:_CRTIMP int __cdecl fclose(FILE *);
关闭成功返回值0,否则返回⾮零值。
注:在执⾏完⽂件的操作后,要进⾏“关闭⽂件”操作。虽然程序在结束前会⾃动关闭所有的打开⽂件,但⽂件打开过多会导致系统运⾏缓慢,这时就要⾃⾏⼿动关闭不再使⽤的⽂件,来提⾼系统整体的执⾏效率。
例1.打开⽂件并进⾏判断和关闭⽂件
FILE *fp;
fp = fopen("c:\\temp\\", "r");
if(fp == NULL)
printf("fail to open the file! \n");
else
{
printf("The file is open! \n");
fclose(fp);
}
2.3 字符存取函数
函数原型为:
fgets和fgetc的区别_CRTIMP int __cdecl fputc(int, FILE *);
_CRTIMP int __cdecl fgetc(FILE *);
字符读取函数fgetc()可从⽂件数据流中⼀次读取⼀个字符,然后读取光标移动到下⼀个字符,并逐步将⽂件的内容读出。
如果字符读取成功,则返回所读取的字符,否则返回EOF(end of file)。EOF是表⽰数据结尾的常量,真值为-1。另外,要判断⽂件是否读取完毕,可利⽤feof()进⾏检查。未完返回0,已完返回⾮零值。
feof()函数原型为:_CRTIMP int__cdecl feof(FILE *);
例2. fgetc()函数的使⽤
版本1:利⽤feof()函数检查⽂件是否读取完毕
main()
{
FILE *fp;
fp = fopen("c:\\temp\\", "r");
if(fp != NULL)
{
while(!feof(fp))
printf("%c", fgetc(fp));
}
else
printf("fail to open! \n");
fclose(fp);
return0;
}
版本2:利⽤⽂件结束标志EOF(即-1)
#include <stdio.h>
main()
{
char ch;
FILE *fp;
fp = fopen("c:\\temp\\", "r");
if(fp != NULL)
{
ch = fgetc(fp);
while(ch != EOF)
{
putchar(ch);
ch = fgetc(fp);
}
}
else
printf("fail to open! \n");
fclose(fp);
return0;
}
版本3 - 重构版本2
#include <stdio.h>
main()
{
char ch;
FILE *fp;
if((fp = fopen("", "r")) != NULL)
while((ch = fgetc(fp)) != EOF)
putchar(ch);
else
printf("fail to open! \n");
fclose(fp);
return0;
}
若要将字符逐⼀写⼊⽂件,⽤fputc()函数。⽰例为:例3. fputc()函数的使⽤
#include <conio.h>
main()
{
char filename[20], ch;
FILE *fp;
printf("Enter a filename: ");
scanf("%s", filename);
printf("Enter some characters to output to file: ");
if((fp = fopen(filename, "w")) == NULL)
printf("fail to open! \n");
else
{
while((ch = getche()) != '\015')
fputc(ch, fp);
}
fclose(fp);
return0;
}
2.4 字符串存取函数
函数原型为:
_CRTIMP int __cdecl fputs(const char *, FILE *);
_CRTIMP char * __cdecl fgets(char *, int,FILE *);
fgets函数的作⽤是从指定⽂件读⼊⼀个字符串,如:fgets(str, n, fp);
参数n为要求得到的字符个数,但只从fp指向的⽂件输⼊n-1个字符,然后在最后加⼀个'\0'字符,因此得到的字符串共有n个字符,把它们放在字符数组str中。如果在读完n-1个字符之前遇到换⾏符或EOF,读⼊结束。
fputs函数的作⽤是向指定⽂件输出⼀个字符串,如:fputs("Hey", fp);
把字符串"Hey"输出到fp指向的⽂件。fputs函数的第⼀个参数可以是字符串常量、字符数组名或字符型指针。若输出成功,则返回0,否则返回EOF。
实例略
2.5 格式化存取函数
函数原型为:
_CRTIMP int __cdecl fprintf(FILE *, const char *,...);
_CRTIMP int __cdecl fscanf(FILE *, const char *,...);
它们与printf和scanf函数相仿,都是格式化读写函数。不同的是:fprintf和fscanf函数的读写对象不是终端(标准输⼊输出),⽽是磁盘⽂件。printf函数是将内容输出到终端(屏幕),因此,fprintf就是将内容输出到磁盘⽂件了。
实例4. fprintf和fscanf函数的使⽤
void main()
{
FILE *fp;
int num = 10;
char name[10] = "Leeming";
char gender = 'M';
if((fp = fopen("", "w+")) == NULL)
printf("can't open the file! \n");
else
fprintf(fp, "%d, %s, %c", num, name, gender);
//将数据格式化输出到⽂件中
fscanf(fp, "%d, %s, %c", &num, name, &gender);
//从⽂件中格式化读取数据
printf("%d, %s, %c \n", num, name, gender);
//格式化输出到屏幕
fclose(fp);
}
2.6 指针重返函数
函数原型为:
_CRTIMP void __cdecl rewind(FILE *);;
rewind函数的作⽤是使位置指针重返回⽂件的开头,属于⽂件的定位。
3. ⼆进制⽂件操作
3.1数据块存取函数
函数原型:
_CRTIMP size_t __cdecl fread(void *, size_t, size_t, FILE *);
_CRTIMP size_t __cdecl fwrite(const void *,size_t, size_t, FILE *);
当要求⼀次存取⼀组数据(如,⼀个数组、⼀个结构体变量的值),fread和fwrite函数可以解决该类问题。它们的调⽤形式⼀般为:
fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);
buffer:对于fread来说,指的是读⼊数据的存放地址;对于fwrite来说,是要输出数据的地址。
size:读写数据时,每笔数据的⼤⼩
count:读写数据的笔数
fp:⽂件指针
实例5. fread和fwrite函数的使⽤
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论