文件与文件指针
文件操作------读(Read)/写(Write)
将数据从磁盘文件读取至内存(读)
将数据从内存存放至磁盘文件上(写)
数据的输入输出都是相对内存而言
根据数据的组成形式,C语言将文件分为两种: 文本文件(Text File)/二进制文件(Binary File)。文本文件又称ASCII文件,是一个字符序列,文件中的内容以ASCII字符的形式存在。
本期学习的知识点:
文件的打开与关闭;文件的读写;格式化读写;块数据的读写;位置指针的读写。
打开函数:fopen
关闭函数:fclose
- fputc------将字符写入文件
- fgetc------从文件中读出一个字符
- fputs------将字符串写入文件
- fgets------从文件读取字符串
- fprintf---------将内容写入文件
- fscanf---------从文件读取内容给变量
- fwrite-----将内容写入文件
- fread-----从文件中读取内容变量
- rewind--------文件位置指针回到文件开头
- fseek---------改变文件位置指针的通用函数
- ftell----------确知文件位置指针相对于文件头的位置
struct FILE
{
short level; //缓冲区使用程度
unsigned flags; //文件状态标志
char fd; //文件描述符
unsigned char hold; //若无文件缓冲区,则不读取数据
short bsize; //缓冲区大小
unsigned char*buffer; //缓冲区位置
unsigned char*curp; //指向缓冲区的指针
unsigned istemp; //临时文件指示器
short token; //用于有效检验
};
/*对一个文件进行操作时,程序员需要定义一个FILE类型的指针,也成为文件指针:FILE *fp
随后让fp指向该文件对应的文件结构体变量,就可以获取该文件的相关信息,进而进行读写操作。因此文件指针是文件操作的基础和关键。*/
文件的打开与关闭
打开函数:fopen
关闭函数:fclose
fopen原型:
FILE *fopen(char *filename,char *mode);
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
fp=fopen("/Users/mima0000/projects-c/C showfiles/main.c","r");
if(!fp)
{
printf("can't open file.\n");
exit(1);
}
}
fclose原型:
int fclose(FILE *fp);
#include <stdio.h>
#include<stdlib.h>
int main() {
FILE *fp;
fp = fopen("/Users/mima0000/projects-c/C showfiles/main.c", "r");
if (fp == NULL) {
printf("无法打开文件");
return 1;
}
// 其他操作
fclose(fp);
return 0;
}
文件的读写
1.fputc------将字符写入文件
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char ch;
fp=fopen("/Users/mima0000/projects-c/C showfiles/new.txt","w");
if(fp==0)
{
printf("file error\n");
exit(1);
}
printf("Enter a text(end with '#'):\n");
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);
ch=getchar();/*这句话的作用是从标准输入(通常是键盘)读取一个字符,并将其赋值给变量ch。在这段代码中,
它用于获取用户输入的文本中的每个字符,直到遇到"#"*/
}
fclose(fp);
return 0;
}
2.fgetc------从文件中读出一个字符
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char ch;
fp=fopen("/Users/mima0000/projects-c/C showfiles/new.txt","r");
if(fp==0)
{
printf("file error\n");
exit(1);
}
while ((ch=fgetc(fp))!=EOF)
{
putchar(ch);
}
putchar('\n');//用于将一个字符输出到标准输出(通常是屏幕)。在这段代码中,它被用来将用户输入的每个字符逐个输出到屏幕上。
fclose(fp);
return 0;
}
3. fputs------将字符串写入文件
4.fgets------从文件读取字符串
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
int main() {
FILE *fp;
char str[N];
int lines = 0;
// 打开文件
fp = fopen("/Users/mima0000/projects-c/C showfiles/new.txt", "a+");
if (fp == 0) {
printf("file error");
exit(1);
}
// 从标准输入读取字符串并写入文件,直到遇到字符串"$"为止
fgets(str, sizeof(str), stdin);
while (strcmp(str, "$") != 0) {
fputs(str, fp);
fputc('\n', fp);
fgets(str, sizeof(str), stdin);
}
// 将文件指针重新定位到文件开头
rewind(fp)
// 逐行读取文件内容并打印出来
while (fgets(str, N, fp) != NULL) {
printf("%s", str);
lines++;
}
// 关闭文件
fclose(fp);
// 输出文件中的行数
printf("the file has %d lines.", lines);
return 0;
}
格式化读写
1.fprintf---------将内容写入文件
原型:
int fprintf(FILE *fp,const char * format,输出参数1,输出参数2...);
2.fscanf---------从文件读取内容给变量
原型:
int fscanf(FILE *fp,const char * format,地址1,地址2...)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100 //存放记录条数
typedef struct Student
{
int ID;
char name[20];
double score;
int rank; //次名初始为0
}STU;
int ReadFile(char *fname,STU st[]); //从文件读出原始数据
void SortRank(STU st[],int n); //根据成绩进行排名
void WriteFile(char *fname,STU st[],int n); //将排名次后的记录存文件并输出
int main()
{
STU stu[N]; //定义一个结构体数组存放学生记录
char filename[50]; //文件名
int num=0;
puts("Please input score file name:\n");
scanf("%s",filename); //读入原始文件名
num=ReadFile(filename,stu); //调用函数将文件读记录到结构体数组
SortRank(stu,num); //调用函数进行成绩排序并求名次
puts("Please input sorted file name:\n");
scanf("%s",filename); //读入排序后目标文件名
WriteFile(filename,stu,num); //将排名此后的记录文件并输出
return 0;
}
int ReadFile(char *fname,STU st[])
{
int i=0; //此处i应该初始化为0
FILE *fp; //定义文件指针
fp=fopen(fname,"r"); //打开文本文件准备读入数据
if(fp==0) //如果文件打开失败,将权限交给操作系统
{
puts("source file error\n");
exit(1);
}
fscanf(fp,"%d%s%lf%d",&st[i].ID,st[i].name,&st[i].score,&st[i].rank);
/*从文件读取内容赋给变量,这里:语句scanf("%d",&a)等价于fscanf(stdin,"%d",&a)*/
/*这里使用了C语言函数feof:该函数作用是,当位置指针指向文件尾时,返回一个非0值,否则返回0,其原型:int feof(FILE *fp)*/
while(!feof(fp)) //当文件结未结束时进入循环
{
i++;
fscanf(fp,"%d%s%lf%d",&st[i].ID,st[i].name,&st[i].score,&st[i].rank);
}
fclose(fp); //关闭文件
return i; //返回实际记录条数
}
void SortRank(STU st[],int n)
{
int i,j,k;
STU temp;
for(i=0;i<n-1;i++) //简单选择排序法
{
k=i; //k用来保存本趟最大分数的结构体下标
for(j=i+1;j<n;j++)
if(st[j].score>st[k].score) //比较的依据是结构体的分数成员
k=i; //每趟任务是找出分数最大的元素
if(k!=i)
{
temp=st[i];
st[i]=st[k];
st[k]=temp;
}
}
st[0].rank=1;
for(i=1;i<n;i++)
{
if(st[i].score==st[i-1].score)
st[i].rank=st[i-1].rank;
else st[i].rank=i+1;
}
}
void WriteFile(char *fname,STU st[],int n)
{
int i;
FILE *fp;
fp=fopen(fname,"w"); //以w的方式打开文件,准备写入内容
if(fp==0) //文件打开失败
{
puts("create new file error\n");
exit(1);
}
for(i=0;i<n;i++) //打开成功
{
fprintf(fp,"%d %-8s\t%.2f%6d\n",st[i].ID,st[i].name,st[i].score,st[i].rank); //将内容写入文件
printf("%d %-8s\t%.2f%6d\n",st[i].ID,st[i].name,st[i].score,st[i].rank); //在屏幕输出内容
}
fclose(fp);
}
块数据的读写
1.fwrite-----将内容写入文件
指定起始位置开始的指定字节数的内容世界写入到指针打开的文件中.从内存地址buffer开始,将连续的n*size个字节的内容原样复制到fp打开的文件里,该函数值返回的是实际写入的数据块个数。
原型:
int fwrite(const void *buffer,int size,int n,FILE *p);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Student
{
int ID;
char name[20];
double score;
}STU;
int main()
{
FILE *fp;
STU stu[3]={{1001,"xinyi",77},{1002,"Lan",100},{1003,"Kid",99}};
fp=fopen("/Users/mima0000/projects-c/C showfiles/new.txt","wb");
if(fp==0)
{
puts("file error\n");
exit(1);
}
fwrite(stu,sizeof(STU),3,fp);
fclose(fp);
return 0;
}
- fread-----从文件中读取内容变量
读取从当前位置开始的指定字节数的内容,然后直接存到内存指定的起始地址开始的空间。从fp打开的文件当前位置开始,连续读取n*size个字节的内容,存入buffer作为首地址的内存空间内,该函数的返回值是实际读入的数据块个数。
原型:
int fread(void *buffer,int size,int FILE *p);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 5
typedef struct Student
{
int ID;
char name[20];
double score;
}STU;
int main()
{
FILE *fp;
STU stu[N];
int i=0,num;
fp=fopen("/Users/mima0000/projects-c/C showfiles/new.txt","rb");
if(fp==0)
{
puts("file error\n");
exit(1);
}
fread(&stu[i],sizeof(STU),1,fp);
while (!feof(fp))
fread(&stu[++i],sizeof(STU),1,fp);
num=i;
for(i=0;i<num;i++)
printf("%d %-8s \t%.2f\n",stu[i].ID,stu[i].name,stu[i].score);
fclose(fp);
return 0;
}
位置指针的定位
1.rewind--------文件位置指针回到文件开头
原型:
void rewind(FILE *fp);
2.fseek---------改变文件位置指针的通用函数
原型:
int fseek(FILE *fp,long offset,int from);
offset为移动的字节数,from为移动的起始位置。将文件位置指针从from开始移动offset字节。执行成功返回0,执行失败返回非0.
3.ftell----------确知文件位置指针相对于文件头的位置
原型:
long ftell(FILE *fp);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 5
typedef struct Student
{
int ID;
char name[20];
double score;
int rank;
}STU;
void Diy();
void Menu();
int ReadTextFile(char *fname,STU st[]);
void PrintScreen(STU st[],int n);
int ReadBiFile(char *fname,STU st[]);
void WriteBiFile(char *fname,STU st[],int n);
void CopyFile(char *fname1,char *fname2);
void Clear(STU st[],int n);
int main()
{
STU stu[N];
char filename1[20],filename2[20];
int num=0;
int choice;
do
{
Diy();
Menu();
puts("Please input your choice:");
scanf("%d",&choice);
switch (choice)
{
case 1:
puts("Plaes input score txt file name:\n");
scanf("%s",filename1);
num=ReadTextFile(filename1,stu);
break;
case 2:
PrintScreen(stu,num);
break;
case 3:
puts("Please input binary file name:\n");
scanf("%s",filename1);
WriteBiFile(filename1,stu,num);
break;
case 4:
puts("Please input binary file name:\n");
scanf("%s",filename1);
num=ReadBiFile(filename1,stu);
break;
case 5:
puts("Input two filename:\n");
scanf("%s%s",filename1,filename2);
CopyFile(filename1,filename2);
break;
case 6:
Clear(stu,num);
break;
case 0:
puts("Exit!!!\n");
break;
default:
puts("Error!!!");
}
} while (choice);
}
int ReadTextFile(char *fname,STU st[])
{
int i=0;
FILE *fp;
fp=fopen(fname,"r");
if(fp==0)
{
puts("file error!");
exit(1);
}
fscanf(fp,"%d%s%lf%d",&st[i].ID,st[i].name,&st[i].score,&st[i].rank);
while (!feof(fp))
{
i++;
fscanf(fp,"%d%s%lf%d",&st[i].ID,st[i].name,&st[i].score,&st[i].rank);
}
fclose(fp);
return i;
}
void WriteBiFile(char *fname,STU st[],int n)
{
FILE *fp;
fp=fopen(fname,"wb");
if(fp==0)
{
puts("file error!");
exit(1);
}
fwrite(st,sizeof(STU),n,fp);
fclose(fp);
}
int ReadBiFile(char *fname,STU st[])
{
int i=0;
FILE *fp;
fp=fopen(fname,"rb");
if(fp==0)
{
puts("file error!");
exit(1);
}
fread(&st[i],sizeof(STU),1,fp);
while (!feof(fp))
{
i++;
fread(&st[i],sizeof(STU),1,fp);
}
fclose(fp);
return i;
}
void PrintScreen(STU st[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d %-8s\t%.2f%6d\n",st[i].ID,st[i].name,st[i].score,st[i].rank);
}
void CopyFile(char *fname1,char *fname2)
{
FILE *fp1,*fp2;
char ch;
fp1=fopen(fname1,"r");
fp2=fopen(fname2,"w");
if(fp1==0||fp2==0)
{
puts("File open error!\n");
exit(1);
}
while ((ch=fgetc(fp1))!=EOF)
{
fputc(ch,fp2);
}
fclose(fp1);
fclose(fp2);
}
void Menu()
{
puts("==============0.退出=============================");
puts("==============1.从文本文件中读取信息================");
puts("==============2.屏幕显示所有信息===================");
puts("==============3.将信息写入二进制文件================");
puts("==============4.从二进制文件读取信息================");
puts("==============5.原样复制文件=======================");
puts("==============6.清空结构体数组中的内容===============");
}
void Clear(STU st[],int n)
{
int i;
for(i=0;i<n;i++)
{
st[i].ID=0;
strcpy(st[i].name," ");
st[i].score=0;
st[i].rank=0;
}
}
void Diy()
{
puts("========APLEXIA=========");
}