操作文件
认识文件
什么是文件
通常计算机包含各种不同类型的文件,例如照片、音乐、.c文件等
文件包含程序文件和数据文件
将数据的输入和输出的过程称为数据流
一个文件名包含文件路径、文件标识符、文件后缀
例如:D:\vscode\coin\hello world.exe
后缀名exe(可执行文件)、txt(文本文件)、doc(word文件)、mp4(视频文件)、mp3(音频文件)等
文件的分类
数据文件分为ASCII文件和二进制文件
数据在内存中是以二进制的形式存储的
文件缓冲区
从磁盘中读取数据,会先将数据存储到输入文件缓冲区中,
等文件缓冲区装满了之后发送到程序数据区
输出文件到磁盘中,会现将数据存储到输出文件缓冲区中,
等文件缓冲区装满了之后在发送给磁盘
graph RL 磁盘 --> 输入文件缓冲区 输入文件缓冲区 --> 程序数据区 程序数据区 --> 输出文件缓冲区 输出文件缓冲区 --> 磁盘文件的操作
对文件的操作方法
graph LR 打开文件 ---> 读取文件内容 --->关闭文件 打开文件 ---> 写入文件内容 --->关闭文件 打开文件 ---> 删除文件内容 --->关闭文件 打开文件 ---> 修改文件内容 --->关闭文件打开文件
打开文件不同于我们操作系统打开文件
打开文件的方法为:
fopen(文件名, 操作模式)
例如:
fopen("D://vscode//coin//hello world.txt","r"); //当打开的文件与代码文件在同一目录下时,则可以省去路径;路径"\",替换为"/" "//" "\\"
//fopen("hello world.txt","r");
fopen为打开函数,文件名为需要打开的文件,操作模式为需要对文件进行何种操作
一旦文件被打开,在内存中开辟区域存放文件的有关信息(如文件的名字、文件的位置、文件的状态等)并返回此信息
定义一个FILE类型的指针变量指向被打开文件,可以将文件信息和指针变量进行关联。之后都可以对文件型指针变量进行操作
打开文件的常用方法为:
FILE *fp
fp = fopen(文件名, 操作模式)
打开模式
-
“r”读模式;允许对文件读取信息。若文件名不正确,则报错
示例:
#include "stdio.h" void main() { int i; FILE *fp; fp = fopen("hello world.txt", "r"); for (i = 0; i < 20; i++) printf("%c", fgetc(fp)); // printf("%d",fp->); i = fclose(fp); printf("%d", i); }
结果:
hello world 0 Press any key to continue
-
“w”写模式;允许向文件写入信息。若文件不存在,则创建一个文件
示例:
#include "stdio.h" void main() { int i; char x = 'Q'; FILE *fp; fp = fopen("time.txt", "w"); for (i = 0; i < 20; i++) fputc(x, fp); i = fclose(fp); printf("%d", i); }
结果:
0 Press any key to continue
代码运行后在目录下双击文件打开后会显示文件内容(这里运行后文件内容为20个'Q');如果将
char x = 'Q';
修改为char x = 'W';
并运行,那么文件内容则为20个'W',即使目录下有相同的文件,文件内容也会为20个'W',相当于代码每运行一次,就会重新创建一次文件(如果目录下已有相同的文件,则会进行替换) -
“a”追加模式;允许在文件末尾添加信息。若文件名不正确,则报错
示例:
#include "stdio.h" void main() { int i; char x = 'E'; FILE *fp; fp = fopen("time.txt", "a"); for (i = 0; i < 20; i++) fputc(x, fp); i = fclose(fp); printf("%d", i); }
结果:
0 Press any key to continue
代码运行后在目录下双击文件打开后会显示文件内容(如果文件有内容的话,则会在末尾添加20个'E')
-
“rb” “wb” “ab”打开二进制文件,其他与以上3个相同
-
“r+” “w+” ”a+”允许对文件读取和写入信息,其他与前3个相同
示例:
#include "stdio.h" void main() { int i; char x = 'Q'; FILE *fp; fp = fopen("hello world.txt", "r+"); for (i = 0; i < 20; i++) printf("%c", fgetc(fp)); for (i = 0; i < 20; i++) fputc(x, fp); i = fclose(fp); printf("%d", i); }
结果:
hello world 0 Press any key to continue
代码运行后在目录下双击文件打开后会显示文件内容(如果文件有内容的话,则会在末尾添加20个'Q')
-
“rb+” “wb+” “ab+”允许对文件读取和写入信息,打开二进制文件,其他与前3个相同
注:文件名和操作模式都要使用双引号
关闭文件
文件使用后需要关闭文件,如果没有及时关闭文件可能会导致数据的丢失。关闭成功返回一个数值0,否则返回EOF(-1)
fclose(文件指针)
文件的读写
文件打开之后,根据文件的打开模式,可以进行读写
向文件读取字符
fgetc( fp )
功能:从fp指向的文件获取一个字符。如果读取成功返回获取的字符,读取失败则返回文件结束标志EOF(-1)
示例:
#include "stdio.h"
void main()
{
FILE *fp;
fp = fopen("hello world.txt", "r");
char a;
a = fgetc(fp);
while (a != EOF)
{
printf("%c", a);
a = fgetc(fp);
}
fclose(fp);
}
结果:
hello world
hello world
hello world
Press any key to continue
向文件写入字符
fputc( c , fp )
功能:向fp指向的文件写入一个字符。如果写入成功返回写入的字符,写入失败则返回文件结束标志EOF(-1)
实例:将hello world.txt文件的内容复制到copy.txt文件中
示例:
#include "stdio.h"
void main()
{
char a;
FILE *fp1, *fp2;
fp1 = fopen("hello world.txt", "r"); //权限的设定可以减少误操作
fp2 = fopen("copy.txt", "w");
while (a != EOF)
{
a = fgetc(fp1);
fputc(a, fp2);
}
fclose(fp1);
fclose(fp2);
}
结果:
Press any key to continue
代码运行后会在目录下创建复制的文件,双击文件打开后会显示文件内容,文件内容会与被复制的文件内容一样
向文件读取字符串
fgets( str, n , fp )
功能:从fp指向的文件获取一个长度为n-1的字符串,并一次性存入到str字符数组中。如果读取成功返回str指针,读取失败则返回NULL
示例:
#include "stdio.h"
void main()
{
char str[50];
FILE *fp;
fp = fopen("test.txt", "r");
fgets(str, 10, fp); // fgets(str,50,fp);
printf("%s", str);
fclose(fp);
}
结果:
test
Press any key to continue
注:
- 读取的n-1个字符,最后加上一个结束标志\0,一共n个字符串
- 遇到换行符或文件结束标志EOF,则将之前的内容存储到str中,不在继续读取字符,表示本次读取结束(最多读取一行)
向文件写入字符串
fputs( str, fp )
功能:将str字符数组中的内容(字符串)写入到fp指向的文件中。如果写入成功返回数字0,写入失败则返回非0的数字
示例:
#include "stdio.h"
void main()
{
char x[100];
FILE *fp;
fp = fopen("experiment.txt", "w");
fputs("hello world\n", fp);
gets(x);
fputs(x, fp);
fclose(fp);
}
结果:
test // "test"由手动输入
Press any key to continue
代码运行后会在目录下创建文件,双击文件打开后会显示文件内容,文件内容为"hello world \n
test"
格式化读写内容
输出:
fprintf(文件指针, 格式字符串, 输出表列)
示例:
#include "stdio.h"
void main()
{
int a = 123;
float b = 3.1415f;
FILE *fp;
fp = fopen("test.txt","w");
fprintf(fp,"%d %5.3f",a,b);
fclose(fp);
}
结果:
Press any key to continue
代码运行后会在目录下创建文件,双击文件打开后会显示文件内容,文件内容为"123 3.141"
输入:
fscanf(文件指针, 格式字符串, 输入表列)
示例:
#include "stdio.h"
void main()
{
int a;
float b;
FILE *fp;
fp = fopen("test.txt","r");
fscanf(fp,"%d %f",&a,&b);
printf("%d %f",a,b);
fclose(fp);
}
结果:
123 3.141000
Press any key to continue
与printf、scanf函数相同,不同点在于不是输出到黑框的终端或在终端输入信息,而是向文件写入信息或读取信息
向文件读取一个数据块
fread(buffer, size, count, fp )
/*
参数:
buffer: 读取的数据存入内存地址
size: 读取的字节大小
count: 读取数据的个数
fp: 读取的文件指针
返回值: 返回读取数据的个数
*/
读取数据时,数据不经过转换的读取到内存中
示例:
#include "stdio.h"
#include "stdlib.h"
void main()
{
char *s;
s = malloc(100);
FILE *fp;
fp = fopen("testing.txt","r");
fread(s,sizeof(char),100,fp); // sizeof(char) 可以替换为 1
s[100]='\0';
printf("%s",s);
fclose(fp);
}
结果:
testing
testing
testing
testing
Press any key to continue
向文件写入一个数据块
fwrite(buffer, size, count, fp )
/*
参数:
buffer: 待写入的内存地址buffer
size: 写入的字节大小
count: 写入数据的个数
fp: 写入的文件指针
*/
写入数据时,数据不经过转换的读取到内存中
示例:
#include "stdio.h"
#include "stdlib.h"
void main()
{
char *a = "hello world";
FILE *fp;
fp = fopen("tests.txt","w");
fwrite(a,sizeof(char),15,fp);
fclose(fp);
}
结果:
Press any key to continue
代码运行后会在目录下创建文件,双击文件打开后会显示文件内容,文件内容为"hello world"
注:
- 由于fread、fwrite函数读写数据时不会转换数据,因此读取速度快
- 读取二进制文件一般使用fread、fwrite函数
- fgetc、fputc、fgets、fputs、fprintf、fscanf函数是读写字符数据,不建议用读取二进制文件
实例:
读写结构体
示例:
#include "stdio.h"
struct test
{
char name[20];
int age ;
}stu = {"lisi",21};
void main()
{
FILE *fp;
fp = fopen("stu.txt","w");
fwrite(&stu,sizeof(struct test),1,fp);
fclose(fp);
}
结果:
Press any key to continue
代码运行后会在目录下创建文件,双击文件打开后会显示文件内容,文件内容为"lisi ......(省略号表示其它内容,也可能是乱码)"
复制二进制文件出错!
示例:
#include "stdio.h"
void main()
{
char a;
FILE *fp1, *fp2;
fp1 = fopen("test.exe","r");
fp2 = fopen("copy.exe","w");
while (a != EOF)
{
a = fgetc(fp1);
fputc(a,fp2);
};
fclose(fp1);
fclose(fp2);
}
结果:
Press any key to continue
代码运行后,在目录下 copy.exe 文件与 test.exe 文件的大小不一样
复制二进制文件的正确方法
示例:
void main()
{
char buf[128];
int a;
FILE *fp1, *fp2;
fp1 = fopen("test.exe","rb");
fp2 = fopen("copy.exe","wb");
a = fread(buf,1,128,fp1); //读取的数据个数
while (a != 0)
{
fwrite(buf,1,128,fp2);
a = fread(buf,1,128,fp1);
};
fclose(fp1);
fclose(fp2);
}
结果:
Press any key to continue
代码运行后,在目录下 copy.exe 文件与 test.exe 文件的大小一样
改变文件读写位置
文件的读写总是从文件的开头起始,一直读写到最后,但如果文件内容较多,只需要获取文件某指定位置的数据,这种方法就比较麻烦。不能快速获取指定位置数据
文件读取指针
文件读写标记记录访问的位置
示例:
/*将文件 hello world.txt 的内容复制两次到文件 copy.txt 中,两次之间的内容使用空白行分隔*/
#include "stdio.h"
void main()
{
char buf[10];
int a;
FILE *fp1,*fp2;
fp1 = fopen("hello world.txt","r");
fp2 = fopen("copy.txt","w");
a = fread(buf,1,10,fp1);
while(a != 0)
{
fwrite(buf,1,a,fp2); //size设置读取的最小单元
a = fread(buf,1,10,fp1);
}
//再循环复制一次
fputc('\n',fp2);
fputc('\n',fp2);
rewind(fp1);
a = fread(buf,1,10,fp1);
while(a != 0)
{
fwrite(buf,1,a,fp2);
a = fread(buf,1,10,fp1);
}
fclose(fp1);
fclose(fp2);
}
结果:
Press any key to continue
代码运行后在目录下双击并打开文件后会显示文件内容
rewind函数将读写指针重新指向文件开头
rewind(fp)
将fp指向的文件读写指针重新指向文件开头
fseek函数指定文件读写指针位置
fseek(文件指针,位移量,起始点)
/*
起始点:
0 表示文件开始位置
1 表示当前读写指针位置
2 表示文件末尾位置
*/
示例:
#include "stdio.h"
void main()
{
char buf[10];
int a;
FILE *fp1, *fp2;
fp1 = fopen("a.txt", "r");
fp2 = fopen("b.txt", "w");
fseek(fp1,10,0); //文件指针在文件开头向后移动10个字节位置
//fseek(fp1,-10,2); //文件指针在文件末尾向后移动10个字节位置
a = fread(buf, 1, 10, fp1);
while (a != 0)
{
fwrite(buf, 1, a, fp2);
//fseek(fp1, 10, 1); //文件指针在当前位置向后移动10个字节位置
a = fread(buf, 1, 10, fp1);
}
fclose(fp1);
fclose(fp2);
}
结果:
Press any key to continue
代码运行后在目录下双击并打开文件后会显示文件内容;当起始位置不同时,文件的内容也会不同
文件操作错误检查
读写文件是否存在错误,除了使用函数的返回值来检验以外,还可以使用错误检查读写函数是否正确执行
ferror函数
ferror(fp)
返回值为"0"表示读写正确;返回值为"1"表示读写错误
clearerr函数
将文件错误标志和文件结束标志置为0。当ferror检查到读写函数出现错误,此时应当立即调用clearerr(fp),使得下一轮能正常使用ferror函数进行检查
示例:
#include "stdio.h"
void main()
{
char buf[10];
int a;
FILE * fp1, *fp2;
fp1 = fopen("hello world.txt","r");
fp2 = fopen("copy.txt","w");
a = fread(buf,1,10,fp1);
while(a != 0)
{
fwrite(buf,1,a,fp2);
a = fread(buf,1,10,fp1);
printf("%d",ferror(fp1)); //检查fread函数调用是否有误
if(ferror(fp1)) clearerr(fp1); //当ferror检查到读写函数出现错误,立即调用clearerr(fp1),使得下一轮能正常使用ferror函数进行检查
}
fclose(fp1);
printf("%d",ferror(fp1));
fclose(fp2);
}
结果:
00000000000
Press any key to continue
代码运行后在目录下双击并打开文件后会显示文件内容,文件内容为复制内容
标签:fp,文件,txt,fp1,fp2,操作,fopen From: https://www.cnblogs.com/ruoxianshi/p/17035083.html