C语言文件入门基础

9——文件

程序处理的数据是如何进入计算机内部的,计算机程序计算的结果又要输出到那里去,在c语言的程序的文件使用,这时的输入与输出的设备就针对文件系统了。

9.1 各类的定义

文件:所谓文件是一般指存储作外部介质(如磁盘,磁带)上数据的集合,操作系统是以文件为单位对数据进行管理的,
流:在c语言的标准库中,提供了一套流操作函数,其中包括流的创建(打开文件),撤销(关闭文件),对流的读写(实际上是流对文件的读和写),以及一些与文件操作相关的函数。
c程序启动时会自动创建3个流:标准输入流(stdin),标准输出流(stdout)和标准输出错误流(stderr).
文件分类:

  1. 文本文件:每个字符均与ASCII代码存储,占一个字符。
  2. 二进制文件:由二进制字节代码组成

9.2 文件使用

程序运行时文件或者流时,系统就为此文件开辟一个FILE类型变量,程序使用几个文件,系统就开辟几个FILE类型变量。

typedef struct
{
	short level;				//fill/empty level of buffer 
	unsigned flags;				//文件状态标志 
	char fd;					//文件描述符 
	unsigned char hold;			//Ungetc char if no buffer 
	short bsize;				//缓冲大小 
	unsigned char * buffer;		//数据传输指针 
	unsigned char * curp;		//当前激活指针 
	unsigned istemp;			//临时文件指示器 
	short token;				//用于合法性校和 
 } FILE;

9.3文件的打开与关闭

9.3.1 fopen函数

文件打开操作通过标准库中函数fopen完成,原型为

FILE *fopen(const char *filename,const char *mode);

当文件打开的操作不能正常完成时,函数fopen()返回空指针(0),并把错误存入errno中。

文件打开方式

模式含义
r打开一个文本文件只读
w打开一个文本文件只写
a打开一个文本文件尾部追加
rb打开一个二进制文件只读
wb打开一个二进制文件只写
ab打开一个二进制文件追加
r+打开一个文本文件可读/写
w+创建一个文本文件只读/写
rb+打开一个二进制文件读写
wb+打开一个二进制文件读写
ab+打开一个二进值文件读写

!注意

w+ 打开文件并读写 1. 文件存在,则清空(也即写入空); 2. 文件不存在,则创建文件 ; 3. 文件流定位到开始位置,
所以read() 会得到空。 r+ 打开文件并读写 1. 文件存在,打开文件,文件指针定位到文件开始位置; 2. 文件不存在,
则报错文件不存在。 a+ 打开文件并读添 1. 文件存在,打开文件,文件指针定位到文件开始位置,但不清空;2.
文件不存在,创建文件; 3. 打开后读取时,在文件开头位置,4. 写入时,添加到文章末尾,并且指针位于添加后的末尾,所以再次读取会乱码。

二进制文件类似

9.3.2关闭函数fclose

该函数主要完成关闭流的所有工作。正常完成时返回0,出问题时返回EOF,
原型为:

int fclose (FILE * stream)

fclose正常完成时返回0,出现问题时返回值为EOF

9.3.3 基本过程

FILE * fp;
fp=fopen("路径","打开方式");//切记根据文件与流的关系,选择相应的模式 
if(fp==NULL)				//判断文件打开是否成功 
{
	//不成功的操作 
 } 
 fclose(cp);

9.4 文件的读写操作

9.4.1 判断文件是否结束feof()

函数feof()即可判断文件是否到了结束标志。
函数原型为:

int feof(FILE * stream);

函数的返回值为非0的数,则说明文件指针以指向文件的结尾。

9.4.2 读写字符函数fgetc与fputc

fgetc,从文件当前流所在位置获取一个字符,并将文件指针指示器移到下一个字符处,如果已经到了文件尾,则返回一个EOF,函数原型为:

int fgetc(FILE * stream)

fputc函数完成对字符ch的值写入所指定的文件中,并将文件指针后移一位,fputc函数的返回值是所写入写入字符的值,出错返回EOF

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp;
    int ch;
    if((fp=fopen("e:\\wenjian\\test.txt","w"))==NULL)
    {
        printf("Failure to open demo.txt!\n");
        exit(0);
    }
    while((ch=getchar())!= '\n')
        fputc(ch,fp);
    fclose(fp);
    return 0;
}

9.4.3 读写字符串函数fgets和fputs

c语言中还提供对字符串操作的函数

  1. fgets从文件中读取num-1个字符,并把它们放入str所指向的字符数组中。
    函数形式:

char *fgets(char * str, int num,FILE * stream);

  1. fputs将str指向的文件写入流文件

int fputs(char *str,FILE *stream);

9.4.5 格式化输入,输出函数fscanf()和fprintf()

类型用法跟printf与scanf的用法类似,而这上述两函数只需要在前面加入文件指针,请看函数原型

int fscanf(FILE * stream,char *format,arg_list);
int fprintf(FILE * stream,char *format,arg_list);
实例介绍使用

#include <string.h>
#include <stdio.h>
#include <stdlib.h> 
struct stu
{
	char name[15];
	char num[6];
	float score[2];
}student;
int main()
{
	FILE *fp;
	int i;
	if((fp=fopen("e:\\wenjian\\test.txt","w"))==NULL)
	{
		printf("cannot open file");
		exit(0);
	}
	printf("input data:\n");
	for(i=0;i<2;i++)
	{
		scanf("%s %s %f %f\n",student.name,student.num,&student.score[0],&student.score[1]);
		fprintf(fp,"%s %s %7.2f %7.2f",student.name,student.num,student.score[0],student.score[1]);
	}
	fclose(fp);
	if((fp=fopen("e:\\wenjian\\test.txt","r"))==NULL)
	{
		printf("cannot open file");
		exit(0);
	}
	printf("output data:\n");
	while(fscanf(fp,"%s %s %f %f",student.name,student.num,&student.score[0],&student.score[1]) != EOF)
	{
		printf("%s %s %7.2f %7.2f\n",student.name,student.num,student.score[0],student.score[1]);
	}
	fclose(fp);
	return 0;
}

9.4.6 块读写函数fread()和fwrite()

由于复杂的数据类型无法以整体形式向文件写入或从文件读出,C语言提供成块的读写方式来操作文件,使其数组或结构体等类型可以进行一次性的读写。函数的原型:

size_t fread(void * pointer,size_t size,size_t num ,FILE *stream);
size_t fwrite(void * pointer,size_t size,size_t num ,FILE *stream);
其中size_t是c语言定义的无符号的整型。pointer指向数据的起始位置

%%在此准备一个实例供大家观看,块存储函数的具体应用,使得大家更深入的理解
*** 使用文件存储对班级学生进行高考基本成绩信息的存储与输出,学生的基本信息有学号,姓名,年龄和高考成绩。***

#include <string.h>
#include <stdio.h>
#define N 2      //定义班级学生个数 
void write();	//完成对文件的写入操作 
void read();	//完成对文件的读出操作 

struct student{
	char name[8];
	int num;
	int age;
	float score;
}stu[N];

int main()
{
	int i;
	for (i=0;i<N;i++)
	{
		scanf("%s %d %d %f",stu[i].name,&stu[i].num,&stu[i].age,&stu[i].score);
	}
	write();
	printf("press any key to show data from file\n");
	getchar();
	read();
	return 0; 
}
void write()
{
	FILE *fp;
	int i;
	if((fp=fopen("e:\\wenjian\\test.txt","wb"))==NULL)
	{
		printf("cannot open file\n");
		return ;
	}
	for(i=0;i<N;i++)
	{
		if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)
		{
			printf("file write error\n");
		}
	}
	fclose(fp);
	
}
void read()
{
	FILE *fp;
	int i;
	if((fp=fopen("e:\\wenjian\\test.txt","rb"))==NULL)
	{
		printf("cannot open file\n");
		return ;
	}
	for (i=0;i<N;i++)
	{
		if(fread(&stu[i],sizeof(struct student),1,fp)==1)
		{
			printf("%-10s%8d%6d%12.2f\n",stu[i].name,stu[i].num,stu[i].age,stu[i].score);
		}
		else{
			printf("file read error\n");
			break;
		}
	}
	fclose(fp);
}

9.5 文件指针的定位

函数名函数原型功能
fseekint fseek(FILE * stream,long offset,int origin);根据origin的值移动文件指针
rewindint rewind(FILE * stream);重返文件起始位置
ftellint ftell(FILE * stream);返回文件指针的当前位置
符号常量含义
SEEK_SET0从文件开头计算
SEEK_CUP1重返文件起始位置
SEEK_END2从文件的末尾计算

例如:fseek(fp,5L,0);将文件指针从文件头向下移动五字节
           fseek(fp,5L,2):将文件指针从文件末尾向上移动五字节

9.6 出错检测

在使用各种输入,输出函数时,如果出现错误,除了可以由返回值表现外,还可以使用ferror函数检查
函数原型:

int ferror(FILE * stream);

注意:对同一文件每一次调用输入、输出函数。均产生一个新的ferror函数值,因此在调用一个输出、输入函数,应立即检查ferror函数的值,否则信息会丢失,在执行fopen函数,ferror函数的初始值自动置为0。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
	FILE *stream;
	stream=fopen("e:\\text.txt","w");
	fgetc(stream);
	if(ferror(stream)){
		printf("Error reading from text.dat");
		clearerr(stream);  //重置错误标志并将指针置于EOF 
	}
	fclose(stream);
	return 0;
 } 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值