C语言基础(九)文件相关操作


系列合集 初窥C语言

十、文件

10.1 C文件概述

文件:存储在外部介质上数据的集合,是操作系统数据管理的单位。
使用数据文件的目的:
1)程序和数据分离:数据文件的改动不引起程序的改动
2)数据共享:不同程序可以访问同一数据文件中的数据
3)能长期保存程序运行的中间数据或结果数据

文件分类:
(1)按文件的逻辑结构
记录文件:由具有一定结构的记录组成(定长或不定长)
流式文件:由一个个字符(字节)数据顺序组成
(2)按存储介质
普通文件:存储介质文件(磁盘,磁带等)
设备文件:非存储介质(键盘,显示器,打印机等)
(3)按数据的组织形式
文本文件:ASCII文件,每个字节存放一个字符的ASCII码。
文本文件特点:存储量大,速度慢,便于对字符操作
二进制文件:数据按其在内存中的存储形式原样存放
二进制文件特点:存储量小,速度快,便于存放中间结果

文件处理方式:
缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区
非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区

10.2 文件类型指针

文件结构体 FILE:
缓冲文件系统为每个正使用的文件在内存中开辟了文件信息区,文件信息用系统定义的名为FILE的结构体描述

FILE定义在studio.h中

typedef struct{
    
    
	int _fd;  //	文件号
	int _cleft;  //缓冲区剩下的字符数
	int _mode;  //文件操作方式
	char *_next;  //文件当前读写位置
	char *_buff;  //文件缓冲区位置
}FILE;

文件类型指针:
指针变量说明: FILE *fp;
用法:文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件;文件关闭后,它的文件结构体被释放。
在这里插入图片描述

10.3 文件的打开与关闭

10.3.1 文件的打开

C文件操作用调用库函数实现,包括在studio.h
文件使用方式:打开文件 --文件读、写 --关闭文件
系统自动打开和关闭三个标准文件:
标准输入: 键盘 stdin
标准输出: 显示器 stdout
标准出错输出: 显示器 stderr

打开文件fopen:
函数原型:

FILE   *fopen (char *name, char *mode)

功能:按指定方式打开文件
返回值:正常打开,为指向文件结构体的指针;打开失败,返回NULL
例如:文件的打开与测试

FILE *fp;
fp = fopen("a.c""w");
if(fp == NULL){
    
    
	prentf("file open error\n");
	exit(0);
}

文件的打开方式:

三个基本模式:
“r”(read)模式总是打开一个已经存在的文件,如果文件不存在则出错。
“w”(write)模式建立一个新文件,如果文件已经存在,那么先删除存在的文件,再建立新文件。
“a”(append)打开一个存在的文件,在文件的尾部追加数据。

三个追加符:
“b”(binary)表示二进制文件。
“t”(或默认)表示文本文件。
“+”表示将模式扩展为可读、可写方式。

文件的打开方式 含义
’ r ’ (只读) 为输入打开一个文本文件
’ w '(只写) 为输出打开一个文本文件
’ a '(追加) 向文本文件尾追加数据
’ rb '(只读) 为输入打开一个二进制文件
’ wb '(只写) 为输出打开一个二进制文件
’ ab '(追加) 向二进制文件尾追加数据
’ r+ '(读写) 为读/写打开一个文本文件
’ w+ '(读写) 为读/写建立一个新的文本文件
’ a+ '(读写) 为读/写打开一个文本文件
’ rb+ '(读写) 为读/写打开一个二进制文件
’ wb+ '(读写) 为读/写建立一个新的二进制文件
’ ab+ '(读写) 为读/写打开一个二进制文件

10.3.2 文件的关闭

作用:使文件指针变量与文件“脱离”,释放文件结构体和文件指针
函数原型: int fclose(FILE *fp);
*fp :文件打开时返回的文件类型指针
功能:关闭fp指向的文件
返回值:正常关闭为0,出错为非0
在这里插入图片描述

10.4 文件的读写

10.4.1 fputc函数和fgetc函数

字符I/O:fputc与fgetc
1)fputc
函数原型:

int fputc(int c,FILE *fp)

功能:把一字节代码c写入fp指向的文件中
返回值:成功,返回c;出错,返回EOF
2)fgetc
函数原型: int fgetc(FILE *fp)
功能:从fp指向的文件中读取一字节代码
返回值:正常,返回读到的代码值;读到文件尾或出错为止

终端I/O 文件I/O
#define putc ( ch,fp ) fputc ( ch,fp )
#define getc ( fp ) fgetc ( fp )
#define putchar ( c ) fputc ( c,stdout )
#define getchar ( ) fgetc ( stdin )

示例:
1.从键盘输入字符,逐个存到磁盘文件中,直到输入‘#’为止

#include <stdio.h>
#include <stdlib.h>
int main(){
    
    
	//FILE *fp 是声明,声明fp是指针,用来指向FILE类型的对象。
	FILE *fp;
	char ch,filename[10];
	printf("请输入文件名称:\n");
	scanf("%s",filename);
	if((fp=fopen(filename,"w"))==NULL){
    
    
		printf("open file is false,exit...\n");
		exit(0);
	}
	printf("open file is true,Please input word\n");
	//前面的scanf()在读取输入时会在缓冲区中留下一个字符'\n'
    //所以如果不在此加一个getchar()把这个回车符取走的话,
	//而是会直接取走这个“无用的”回车符,从而导致读取有误。
	ch=getchar();
	//首次获取键盘输入
	ch=getchar();
	while(ch!='#'){
    
    
		//fputc 将字符ch写到文件指针fp所指向的文件的当前写指针的位置
		fputc(ch,fp);
		ch=getchar();
	}
	fclose(fp);
	return 0;
}

输入:
file1.c
computer and c#
输出:
computer and c
2.将一个磁盘文件中的信息复制到另一个磁盘文件

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    
    FILE *in,*out;
	char ch,infile[10],outfile[10];
	printf("enter the infile name:");
	scanf("%s",infile);
	printf("enter the outfile name:");
	scanf("%s",outfile);
	if((in=fopen(infile,"r"))==NULL){
    
    
        printf("cannot open this file\n");
        exit(0);
	}
	if((out=fopen(outfile,"w"))==NULL){
    
    
        printf("cannot open this file\n");
        exit(0);
	}
	ch=fgetc(in);
	// 对feof()来说,站在光标所在位置,向后看看还有没有字符。如果有,返回0;如果没有,返回非0。
	//它并不会读取相关信息,只是查看光标后是否还有内容。
	//
	while(!feof(in)){
    
    
	    fputc(ch,out);
		ch=fgetc(in);
	}
	fclose(in);
	fclose(out);
	return 0;
}

输入:
file1.c
file2.c

10.4.2 fread函数和fwrite函数

数据块I/O:fread与fwrite
函数原型:

size_t fread( void *buffer, size_t size, size_t count, FILE *fp)
size_t fwrite( void *buffer, size_t size, size_t count, FILE *fp)

*buffer,size_t :指向要输入/输出数据块的首地址
size,size_t :每个要读/写的数据块的大小(字节数)
count,FILE:要读/写的数据块的个数
*fp :要读/写的文件指针
功能:读写数据块
返回值:成功,返回读写的块数;出错或文件尾,返回0

示例:从键盘输入4个学生的数据,转存到磁盘文件中,并显示在屏幕上

#include <stdio.h>
#define SIZE 4
struct Student_type
{
    
    
	char name[10];
	int num;
	int age;
	char addr[15];
}stud[SIZE];
void save()
{
    
    
	FILE *fp;
	int i;
	if ((fp = fopen("stu_data", "wb")) == NULL)
	{
    
    
		printf("cant open file\n");
		return;
	}
	for (i = 0; i < SIZE; i++)
	{
    
    
		if (fwrite(&stud[i], sizeof(struct Student_type), 1, fp) != 1)
			printf("file write error\n");
	}
	fclose(fp);
}
void display()
{
    
    
	int i;
	FILE *fp;
	if ((fp = fopen("stu_data", "rb")) == NULL)
	{
    
    
		printf("cannot open file\n");
		return;
	}
	for (i = 0; i < SIZE; i++)
	{
    
    
		fread(&stud[i], sizeof(struct Student_type), 1, fp);
		printf("%-10s %4d %4d %-15s\n", stud[i].name, stud[i].num, stud[i].age, stud[i].addr);
	}
	fclose(fp);
}
int main()
{
    
    
	int i;
	printf("please enter date of studnet:\n");
	for (i = 0; i < SIZE; i++)
	{
    
    
		scanf("%s %d %d %s", stud[i].name, &stud[i].num, &stud[i].age, stud[i].addr);
	}
	save();
    display();
}

10.4.3 fprintf函数和fscanf函数

格式化I/O:fprintf与fscanf
函数原型:

int fprintf ( FILE *fp, const char  *format [argument...])
int fscanf ( FILE *fp,const char  *format [address...] )

功能:按格式对文件进行I/O操作
返回值:成功,返回I/O的个数;失败,出错或文件尾,返回EOF

fprintf (fp, "%d,%6.2f",i,t);
//将i和t按%d,%6.2f格式输出到fp文件
fscanf(fp, "%d,%f",&i,&t);
//将文件中的整型数据输入i,浮点型数据输入t

10.4.4 其他读写函数

字符串I/O:fgets和fputs

char *fgets( char *s, int n,FILE *fp)
int fputs(char *s,FILE *fp)

功能:从fp指向的文件读写一个字符串
返回值:
fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL
fputs正常时返回写入的最后一个字符;出错为EOF

fgets从fp所指文件读n-1个字符送入s指向的内存区,并在最后加上’\0’(若读入n-1个字符前遇到换行符或文件尾(EOF)即结束)
fputs把s指向的字符串写入fp指向的文件

10.5 文件的定位

10.5.1 rewind函数

文件位置指针-----指向当前读写位置的指针
顺序读写:位置指针按字节位置顺序移动
随机读写:位置指针按需要移动到任意位置
函数原型:

void rewind(FILE *fp)

功能:重置文件位置指针到文件开头
返回值:无

示例:从文件中第一次将它内容显示在屏幕上并且复制到另一个文件上

#include<stdio.h>
int main()
{
    
    
    FILE *fp1,*fp2;
    fp1 = fopen("file1.c","r");
    fp2 = fopen("file2.c","w");
    while(!feof(fp1)) putchar(getc(fp1));
    rewind(fp1);
    while(!feof(fp1)) putc(getc(fp1),fp2);
    fclose(fp1);
    fclose(fp2);
}

10.5.2 fseek函数和随机读写

fseek函数
函数原型:

int fseek(FILE *fp, long offset, int from)

功能:改变文件位置指针的位置
返回值:成功,返回0;失败,返回非0;
offset:位移量,类型为long型,表示以from为起点移动的量相对值(字节数)。
from:移动的起始位置。
from取值含义:

from value 宏名 含义
0 SEEK_SET 文件头
1 SEEK_CUR 当前位置
2 SEEK_END 文件尾

示例1:磁盘文件上有4个学生数据,要求读入第1,3学生数据并显示

#include <stdio.h>
#include<stdlib.h>
struct student_type
{
    
        char name[10];
     int num;
     int age;
     char addr[15];
}stud[10];
int main()
{
    
    
    FILE * fp;
    int i;
    if ((fp = fopen( "stu_data" , "rb" )) == NULL)
    {
    
    
    printf( "cannot open file\n " );
    exit(0);
    }
    for (i = 0 ;i < 4;i ++ )
    {
    
    
        fseek(fp,i*sizeof(struct student_type),0);
        fread(&stud[i],sizeof(struct student_type),1,fp);
        printf("%s %d %d %s \n",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
    }
    fclose(fp);
}

示例2:

fseek(fp,10L,SEEK_SET);   //将读写指针移动到离文件头10个字节处
fseek(fp,20L,1);  //将读写指针移动到离当前位置20个字节处
fseek(fp,-10L,2);   //将读写指针移动到离文件末尾处10个字节处。

10.5.3 ftell函数

函数原型:

long ftell(FILE *fp)

功能:返回位置指针当前的位置(用相对文件开头的位移量表示)
返回值:成功,返回当前位置指针位置;失败,返回 -1L

10.6 出错的检测

10.6.1 ferror函数

函数原型:

int  ferror(FILE  *fp)

功能:测试文件是否出现错误
返回值:未出错,0;出错,非0

说明:
1)每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试
2)fopen打开文件时,ferror函数初值自动置为0

10.6.2 clearerr函数

函数原型:

 void  clearerr(FILE  *fp)

功能:使文件错误标志置为0
返回值:无
说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数

10.6.3 feof函数

作用:
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0

EOF:
1)EOF是一个计算机术语,为End Of File的缩写,在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。通常在文本的最后存在此字符表示资料结束。
2)文档的结尾都有一个隐藏字符”EOF”,当程序读取它的时候,就会知道文件已经到达结尾。
3)EOF 的值通常为 -1,但它依系统有所不同。

feof()的原理:
站在光标所在位置,向后看看还有没有字符。如果有,返回0;如果没有,返回非0。它并不会读取相关信息,只是查看光标后是否还有内容。

注意:
1)对于文件来说,无论是空文件,还是存有信息的文件,当文件被打开,光标处于默认的开头时,光标后都有信息,这时候调用feof()来查看光标后是否还有内容,就没意义。
2)我们需要从相同中找不同,先使用getc(),从文件中读取一个字符,让光标向后移动一个字符。这时空文件的光标就已经移动到EOF的后面,这时使用feof()就会返回1了。这才是feof()的正确用法。
3)但要注意,一定要将光标回到文件的开头,因为之前判断文件是否为空时,将光标向前移动了一位,必须要将光标恢复到开头,这样才能保证文件的正常读取。

rewind(p);//将光标跳回到文件开头
分类 函数名
打开文件 fopen()
关闭文件 fclose()
文件定位 fseek() ; rewind() ; ftell()
文件读写 fgetc() , getc() , fputc() , putc() , fgets() , fputs() , getw() , putw() , fread() , fwrite() , fscan() , fprintf()
文件状态 feof() , ferror() , clearerr()

猜你喜欢

转载自blog.csdn.net/qq_43310387/article/details/124245804