主要内容
- 文件概述
- 文件指针
- 文件的打开与关闭
- 文件的读写
文件
把输入和输出的数据以文件的形式保存在计算机的外存储器上,可以确保数据能随时使用,避免反复输入和读取数据
文件概述
- 文件是指一组相关数据的有序集合
- 文件是存储数据的基本单位,可以通过读取文件访问数据。
分类
可以按照不同角度对文件进行分类: – 按存储介质不同,可以分为磁盘文件、磁带文件、打印文件等 – 按存储内容不同,可以分为程序文件和数据文件 – 按访问方式不同,可以分为顺序文件、随机文件和二进制文件 – 按用户不同,可以分为普通文件和设备文件C语言文件分类
• 在C语言中,把文件看作是一个字符的序列 • 根据数据的组织形式可以分为 ASCII 文件和二进制文件 : – ( 1 ) ASCII文件也称为文本文件 ,在磁盘中存放时每个字符对应一个字节,用于存放对应 ASCII 码 – ( 2 )二进制文件是按二进制的编码方式存放文件,将内存中的数据按照其在内存中的存储形式原样输出到磁盘中存放。 • 短整数 968 ( 00000011 11001000B ): – 如果按 ASCII 码的形式输出则占 3 个字节(每个字符占 1 个字节) – 而按二进制形式输出,则在磁盘上占 2 个字节• C 语言版本不同,对文件的处理方式也各有不同,主要有两种方法: • 一种是“缓冲文件系统” • 一种是“非缓冲文件系统”
缓冲文件系统
•缓冲文件系统会自动在内存中为每一个正在使用的文件分配一个缓冲区 • 在写文件时,先将数据放入缓冲区,当缓冲区存满数据后才将缓冲区中的数据写入文件。 • 在读文件时,先一次将一部分数据读入缓冲区,当缓冲区存满数据后才将数据送到程序数据区。 • 缓冲区大小由 C 语言的版本确定,一般为 512 字节非缓冲文件系统
• 非缓冲文件系统就是系统不会在内存中为文件分配缓冲区,所有的文件操作是直接跟文件打交道,这会导致系统整体效率下降文件输入输出函数
• ANSI C 规定了标准的输入输出函数用于文件读写,它们的声明在 stdio.h 文件中文件指针
• 在缓冲文件系统中,每个文件都在内存中分配一个缓冲区,用来存放文件信息 • 信息被存放在一个结构体中,该结构体由系统定义,命名为FILEtypedef struct
{ int level; //缓冲区“满”或“空”的标志
unsigned flags; //文件状态标志
char fd; //文件描述
unsigned char hold; //如果没有缓冲区则不读取字符
int bsize; //缓冲区大小
unsigned char _FAR *buffer; //缓冲区位置
unsigned char _FAR *curp; //指向缓冲区当前数据的指针
unsigned istemp; //临时文件指示器
short token; //用于有效性检查
}FILE;
•
文件指针变量是一个文件结构体类型的指针变量。
定义文件类型指针变量的一般形式为
–
FILE *
指针变量名
;
–
File *fp;
–
//
fp是一个指向FILE结构体类型的指针变量
文件的打开与关闭
• C 语言中文件操作一般包括三个步骤: ( 1 )用 fopen 函数打开文件 ( 2 )进行读写操作 ( 3 )用 fclose 函数关闭文件fopen函数
• fopen 函数用于打开文件,并把结果赋给 FILE 指针变量,它的一般形式为: fopen(文件名,文件打开方式); • “文件名”是要打开的文件名,可以是完整的文件路径FILE *fp;
//fp是一个指向FILE结构体类型的指针变量
fp = fopen("file_data.txt","r");
//以只读方式打开文件file_data.txt
• “ 文件打开方式”是打开文件的访问方式fopen函数,会由于无法打开指定文件而出现错误。
如果出错,fopen函数会返回一个空指针值NULL(NULL在stdio.h中被定义为0)。
例如以“r”方式打开时,文件不存在,要进行错误处理。
FILE *fp;
if( (fp = fopen("file_data.txt","r") ) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fclose函数
• 在操作完一个文件后要关闭文件指针,以释放缓冲区内存,防止其他误操作 • 关闭文件就是使文件指针变量不再指向该文件 • fclose 函数的一般形式为: – fclose (文件类型指针); – fclose(fp);文件的读写
fputc函数
• fputc 函数的作用是将一个字符写入指定文件中 • 它的一般形式为: – fputc (字符型数据,文件指针);【例13.1】从键盘输入文本,并将文本写入磁盘上存储的文本文件file_data.txt中。以字符#作为输入结束标志。
分析:
首先打开文件,然后从键盘循环输入字符,如果字符不是结束标志“#”,那么将字符写入文件,否则关闭文件
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char ch;
if( (fp = fopen("file_data.txt","w")) == NULL ) //打开文件
{ printf("can not open the file\n");
exit(0); //退出程序,必须包含<stdlib.h>头文件
}
ch = getchar();
while(ch != '#' )
{ fputc(ch,fp); //输出字符
ch = getchar();
}
fclose(fp); //关闭文件
}
fgetc函数
• fgetc 函数的作用是从指定的文件中读入一个字符,并作为函数的返回值返回,如果读到文件结束符时,则返回一个文件结束标志 EOF (值为 -1 )。 • fgetc 函数的一般形式为: • fgetc (文件指针);【例13.2】读取文本文件file_data.txt,并将文件中的内容输出到屏幕上。
分析:
首先打开文件,然后反复从文件中读入一个字符,并输出到屏幕,直到文件的结尾,最后关闭文件。
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char ch;
if( (fp = fopen("file_data.txt","r")) == NULL ) //打开文件
{ printf("can not open the file\n");
exit(0); //退出程序
}
ch = fgetc(fp); //从文件中读入一个字符
while(ch != EOF )
{ putchar(ch);
ch = fgetc(fp); //从文件中读入一个字符
}
fclose(fp); //关闭文件
}
fputs函数
• fputs 函数的作用是将字符串写入指定文件中 • 它的一般形式为: • fputs (字符串数据,文件指针); • 字符串数据可以是字符串常量或者字符数组名,写入时字符串最后的‘ \0’ 并不一起写入,也不自动添加回车符。 • 如果写入成功,则函数返回值为 0 ,否则返回值为 EOF【例13.3】从键盘输入一串字符串,并将字符串写入文本文件file_data.txt中。
解决该问题的主要步骤为:
(1)打开文本文件file_data.txt。
(2)从键盘输入一串字符串。
(3)将字符串写入文件中。
(5)关闭文件。
(6)结束程序。
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char str[20];
if( (fp = fopen("file_data.txt","w")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
printf("input the string: ");
gets(str);
fputs(str,fp); //写入字符串
fclose(fp);
}
fgets函数
• fgets 函数的作用是从指定文件中读入指定长度的字符串 • 它的一般形式为: • fgets (字符数组名, n ,文件指针); • 指定的长度由整型数据 n 决定。 • 从文件中读入 n-1 个字符,然后在最后添加一个‘ \0’ 字符作为字符串结束的标志。 • 如果在读完 n-1 个字符之前遇到一个换行符或一个 EOF ,则读入结束。 • 最多只能读入 n-1 个字符,读入的字符被放入参数的字符数组中,读入结束后,将字符数组的首地址作为函数返回值【例13.4】读取文本文件file_data.txt中指定长度的文本,长度由键盘输入,并将读取的内容输出到屏幕上。
解决该问题的主要步骤为:
(1)打开文本文件file_data.txt。
(2)从键盘输入要读取的文本长度。
(3)读入数据。
(4)输出数据。
(5)关闭文件。
(6)结束程序。
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char str[20];
int n;
if( (fp = fopen("file_data.txt","r")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
printf("input the character's number: ");
scanf("%d",&n);
fgets(str,n+1,fp);
printf("%s\n",str);
fclose(fp);
}
fprintf函数
• fprintf 函数将数据按指定格式写入指定文件中,与 printf 函数的作用相似。 • 它的一般形式为: • fprintf (文件指针,格式字符串,输出表列);【例13.5】将指定数据写入文本文件file_data.txt中。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
int i=10,j=12;
double m=1.5,n=2.345;
char s[]="this is a string";
char c='\n';
if( (fp = fopen("file_data.txt","w")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fprintf(fp,"%s%c",s,c);
fprintf(fp,"%d %d\n",i,j);
fprintf(fp,"%lf %lf\n",m,n);
fclose(fp);
}
文件中保存的文本与程序中的数据一致,且格式与指定格式相同
【例13.6】按照每行5个数,将Fibonacci数列的前40个数写入file_data.txt文件中。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
int f[40];
int i;
if( (fp = fopen("file_data.txt","w")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
for (i=0;i<=39;i++) //求Fibonacci数列
{ if (i==0||i==1)
f[i]=1;
else
f[i]=f[i-2]+f[i-1];
}
for (i=0;i<=39;i++) //写入文件
{ if ((i+1)%5==0)
fprintf(fp,"%10d\n",f[i]);
else
fprintf(fp,"%10d",f[i]);
}
fclose(fp);
}
fscanf函数
• fscanf 函数从指定文件中按指定格式读入数据,与 scanf 函数作用相似。 scanf 是从键盘输入,而 fscanf 是从文件读入。 • fscanf 函数的一般形式为: – fscanf ( 文件指针,格式字符串,输入表列 );【例13.7】以指定格式读取【例13.5】中生成的文件file_data.txt中的数据,并输出到屏幕上
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
int i,j;
double m,n;
char s1[100],s2[100],s3[100],s4[100];
if( (fp = fopen("file_data.txt","r")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fscanf(fp,"%s%s%s%s",s1,s2,s3,s4);
//读入四个单词
fscanf(fp,"%d%d",&i,&j);
//读入两个整型数据
fscanf(fp,"%lf%lf",&m,&n);
//读入两个double类型数据
printf("%s %s %s %s\n",s1,s2,s3,s4);
printf("%d %d\n",i,j);
printf("%lf %lf\n",m,n);
fclose(fp);
}
fwrite函数
• fwrite 函数的作用是将指定长度的数据写入指定文件中。它的一般形式为: • fwrite ( buffer , size , count , 文件指针 ); • buffer 是数据块的指针,一个写入数据的内存地址 • size 是每个数据块的字节数 • count 是要写入多少个 size 字节的数据块 • fwrite 函数主要用于写入二进制文件,因此在打开文件的时候需要以“ wb” 方式打开struct Book_Type
{ char name[10];//书名
int price;//价格
char author[10];//作者名
};
•
如果要将书的信息写入到磁盘中,如下代码实现:
for(i=0;i<2;i++)
{
fwrite(&book[i],sizeof(struct Book_Type),1,fp);
}
【例13.8】通过键盘输入所有2本书的信息,并存储在文本文件file_data.txt中。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ struct Book_Type
{ char name[10];//书名
int price;//价格
char author[10];//作者名
};
FILE *fp;
struct Book_Type book[2];
int i;
if( (fp = fopen("file_data.txt","wb")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
printf("input the book info: \n");
for(i=0;i<2;i++)
{ scanf("%s%d%s",book[i].name,&book[i].price,book[i].author);
fwrite(&book[i],sizeof(struct Book_Type),1,fp);
//读入一条记录
}
fclose(fp);
}
因为是以二进制方式保存,所以记事本中的内容显示为乱码。
fread函数
• fread 函数的作用是从指定文件中读入指定长度的数据块。它的一般形式为: • fread ( buffer , size , count , 文件指针 ); • buffer 是数据块的指针,一个读入数据的内存地址 • size 是每个数据块的字节数 • count 是要读入多少个 size 字节的数据块。 • fread 函数主要用于读取二进制文件,因此在打开文件的时候需要以“ rb” 方式打开。 • 例如: – fread(data,2,3,fp); • data 是一个整型数组名,一个整型数据占用 2 个字节的内存空间 • 此函数调用的功能是从 fp 所指向的文件中读入 3 次(每次 2 个字节)数据,并存储到整型数组 data 中【例13.9】将【例13.8】中已经存有book信息的文件打开,读出信息后显示在屏幕上。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ struct Book_Type
{ char name[10];//书名
int price;//价格
char author[10];//作者名
};
FILE *fp;
struct Book_Type book[2];
int i;
if( (fp = fopen("file_data.txt","rb")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
printf("the book info: \n");
for(i=0;i<2;i++)
fread(&book[i],sizeof(struct Book_Type),1,fp);
for(i=0;i<2;i++)
printf("name=%s,price=%d,author=%s\n",
book[i].name,book[i].price,book[i].author);
fclose(fp);
}
rewind函数
• rewind 函数的作用是使位置指针重新返回指定文件的开头。 • 它的一般形式为: • rewind (文件指针); • 此函数没有返回值。 • 在文件操作中会移动文件的位置指针,可以使用 rewind 函数将位置指针回到文件头部。【例13.10】将指定字符串数据写入文本文件file_data.txt中,并将文件的位置指针重新定位到文件开头,读出文件中的第1个字符数据后显示在屏幕上。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char s[]="abcdefghijklmnopqrstuvwxyz";
char c;
if( (fp = fopen("file_data.txt","w+")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fprintf(fp,"%s",s); //向文件中写入字符串
rewind(fp); //指针返回开始
fscanf(fp,"%c",&c); //读入一个字符
printf("The first character is: %c\n",c);
fclose(fp);
}
fseek函数
• fseek 函数的作用是将文件的位置指针移到指定位置 • 它的一般形式为: • fseek( 文件指针,位移量,起始点 ) ; • 在文件操作中可能需要从文件中的某个位置开始进行读写,此时可以使用 fseek 函数将位置指针移动到指定位置,实现随机读写 • 位移量是以“起始点”为基准移动的字节数( long ) • “ +” 表示向后移动 • “ -” 表示向前移动。 • 例如: – fs eek(fp,40L,0); – // 将位置指针移动到文档开始后 40 个字节的位置 – fseek(fp,30L,1); – // 将位置指针移动到当前位置后 30 个字节的位置 – fseek(fp,-20L,2); – // 将位置指针移 动到文档末尾前 20 个字节的位置
【例13.11】将指定字符串数据写入文本文件file_data.txt中,并将文件的位置指针定位到第5个字符之后,读出第6个字符并显示在屏幕上。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char s[]="abcdefghijklmnopqrstuvwxyz";
char c;
if( (fp = fopen("file_data.txt","w+")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fprintf(fp,"%s",s);
fseek(fp,5L,0);
fscanf(fp,"%c",&c);
printf("The first character is: %c\n",c);
fclose(fp);
}
ftell函数
• ftell 函数的作用是返回文件位置指针的位置,给出当前位置指针相对于文件头的字节数,返回值为 long 型。当函数调用出错时,函数返回 -1L 。 • 一般形式为 : • ftell (文件指针);【例13.12】求出文件中包含的字节数。
分析:
先将文件的位置指针移到文件末尾,再通过返回位置指针的位置来取得文件的字节数。
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
long l;
if( (fp = fopen("file_data.txt","r")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
fseek(fp,0L,SEEK_END); //将文件的位置指针移到文件末尾
l=ftell(fp); //返回位置指针的位置
fclose(fp);
printf("the length of file is %ld\n",l);
}
feof函数
• feof 函数的作用是判断文件指针是否在文件末尾,如果在文件末尾,则返回非 0 ,否则返回 0 。 • 一般形式为 : • feof (文件指针);【例13.13】判断文件指针是否在文本文件file_data.txt的末尾,并给出相应提示。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
char ch;
if( (fp = fopen("file_data.txt","r")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
do
{ ch=fgetc(fp);
putchar(ch);
}while (!feof(fp)); //判断是否到达文件尾
if(feof(fp)) printf("\nWe have reached end-of-file\n");
//判断是否到达文件尾
fclose(fp);
}
ferror函数
• ferror 函数的作用是检查文件中是否有错误,如果有错,则返回非 0 ,否则返回 0 。 • 它的一般形式为 : – ferror (文件指针);【例13.14】判断的文本文件file_data.txt是否有错误,并给出相应提示。
编写程序如下:
#include<stdio.h>
#include<stdlib.h>
void main()
{ FILE *fp;
if( (fp = fopen("file_data.txt","r")) == NULL )
{ printf("can not open the file\n");
exit(0);
}
if(ferror(fp))
printf("Error reading from file_data.txt\n");
else
printf("There is no error\n");
fclose(fp);
}
标签:fp,文件,C语言,详解,file,txt,data,指针
From: https://blog.csdn.net/m0_64148419/article/details/140241989