阿鲤将以以下顺序向大家介绍C语言的文件操作
1:什么是文件
2:文件名
3:文件类型
4:文件缓冲区
5:文件指针
6:文件的打开与关闭
7:文件的顺序读写
8:文件的随机读写
9:文件的结束判定
一:什么是文件?
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件
程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
二:文件名
一个文件唯一的标识就是文件名,便于用户的识别和引用。
文件名包括三部分:文件路径+文件名主干+文件后缀 eg:E:\code\test.exe
为了方便起见,文件名主干通常被称为文件名。
三:文件类型(vs2017上实现)
根据数据的组织型式,数据文件被称为文本文件或二进制文件;
数据在内存中以二进制的形式存储,如果不加转换的输出,就是二进制文件;
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
例如:整数10000如果以文本文件(以ASII输出)其就占内存5字节;而如果以二进制文件输出其就占四个字节10 27 00 00(十六进制存储);
eg:
int main()
{
int a = 1000;
FILE *pf = fopen("text.txt", "wb");
fwrite(&a, 4, 1, pf);
fclose(pf);
pf = NULL;
system("pause");
return 0;
}
这是以二进制形式写入文件,其运行的结果在文件内表现如下:
(二进制文件存储在视觉上往往很混乱)
当然如果你想要看到你所写的二进制形式,可以采用一下途径:
视图->解决方案资源管理器->test(自己的文件名)->打开方式->二进制编译器
四:文件缓冲区
ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
五:文件指针
文件指针,便是只想文件的指针,保存文件地址的指针,其初始化使用FILE ;使用FILE,在vs2017环境下,使用stdio.h引进;
请看下图:
此图是vs2017中对FILE的介绍,可以看出FILE是用一个结构体来定义的,并且在不同的c编译器中,对FILE的定义是大同小异的。
eg1:
int main()
{
FILE *p;
return 0;
}
其中p就是指向一个文件的文件指针;就像下图;
六:文件的打开与关闭
ANSCI规定打开函数使用fopen,关闭函数使用fclose
eg1:
FILE *pf = fopen("text.txt", "wb");
fclose(pf);
打开方式如下:
eg2(实例代码):
int main()
{
int a = 1000;
FILE *pf = fopen("text.txt", "wb");
assert(pf != NULL);
fwrite(&a, 4, 1, pf);
fclose(pf);
pf = NULL;
system("pause");
return 0;
}
七:文件的顺序读写
下面是对上述函数所举的一些例子:
eg1:fgetc(读文件)
int main()
{
FILE *pf = fopen("E:\\hello.txt","r");
assert(pf != NULL);
int ch = fgetc(pf);//读字符
printf("%c\n", ch);
return 0;
}
eg2:fputc(写文件)
int main()
{
FILE *pf = fopen("E:\\hello.txt","w");
assert(pf != NULL);
fputc('b',pf);//写字符
fclose(pf);
pf = NULL;
return 0;
}
eg3:fgets(读文件:字符串)
int main()
{
FILE *pf = fopen("E:\\hello.txt", "r");
char buff[100];
assert(pf != NULL);
while (fgets(buff, strlen(buff), pf) != NULL)
{
printf("%s",buff);
}
fclose(pf);
pf = NULL;
return 0;
}
eg4:fputs(写文件:字符串)
int main()
{
FILE *pf = fopen("E:\\hello.txt", "w");
assert(pf != NULL);
fputs("hello", pf);//覆盖之前内容 ;
fclose(pf);
system("pause");
return 0;
}
eg5:fscanf(多用与结构体中:读)
typedef struct Student
{
char name[20];
int age;
}Student;
int main()
{
Student stu1 = { "zhangsan",19 };
Student stu2 = { 0 };
FILE *pf = fopen ("E:\\hello.txt", "r");
assert(pf != NULL);
fscanf(pf, "%s%d", stu2.name, &stu2.age);
printf("%s,%d", stu2.name, stu2.age);
system("pause");
return 0;
}
eg6:(格式化书写,用于结构体)
typedef struct Student
{
char name[20];
int age;
}Student;
int main()
{
Student stu1 = { "zhangsan",19 };
Student stu2 = { 0 };
FILE *pf = fopen ("E:\\hello.txt", "r");
assert(pf != NULL);
fprintf(pf, "%s %d", stu1.name, stu1.age);
printf("%s,%d", stu2.name, stu2.age);
return 0;
}
eg7:fread
int main()
{
Student stu1 = { "zhangsan",19 };
Student stu2 = { 0 };
FILE *pf = fopen("E:\\hello.txt", "rb");//读 返回读到的数量
assert(pf != NULL);
fread(&stu2, sizeof(Student), 1, pf);
printf("%s,%d", stu2.name, stu2.age);
fclose(pf);
pf = NULL;
system("pause");
return 0;
}
eg8:fwrite
int main()
{
Student stu1 = { "zhangsan",19 };
Student stu2 = { 0 };
FILE *pf = fopen("E:\\hello.txt", "wb");//写
assert(pf != NULL);
fwrite(&stu1, sizeof(Student), 1, pf);//要写的数据 写的数据大小 次数 写到哪里
printf("%s,%d", stu2.name, stu2.age);
fclose(pf);
pf = NULL;
system("pause");
return 0;
}
八:文件的随机读写
根据文件指针的位置和偏移量来定位文件指针
而fseek就是来偏移的
eg1:
int main()
{
FILE *pf = fopen("E:\\hello.txt", "r");
assert(pf != NULL);
char ch[13] = "hellowangrui";
char ch2;
//fseek(pf, -3, SEEK_END);//SEEK_END文件的尾巴
//fseek(pf, 3, SEEK_SET);//SEEK_SET 设置文件指针为文件开始的位置
fseek(pf, 3, SEEK_SET);
fseek(pf, -2, SEEK_CUR);//SEEK_CUR当前文件指针位置
//fwrite(&ch, sizeof(char), strlen(ch), pf);
while ((fread(&ch2, sizeof(char), 1, pf)) > 0)
{
putchar(ch2);
}
fclose(pf);
pf = NULL;
system("pause");
return 0;
}
eg2:rewind(让文件回到起始位置),ftell(计算偏移量)
int main()
{
FILE *pf = fopen("text.txt", "w+");
assert(pf != NULL);
char ch[10] = "hellorui";
fwrite(&ch, sizeof(char), strlen(ch), pf);
long int size = ftell(pf);//计算偏移量
printf("%d\n", size);
rewind(pf);//将文件指针拉回文件起始位置
char ch2;
while ((fread(&ch2, sizeof(char), 1, pf)) > 0)
{
putchar(ch2);
}
system("pause");
return 0;
}
九:文件的结束判定
被错误使用的 feof
牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
- 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或者NULL(fgets)
例如:
fgetc判断是否为EOF.
fgets判断返回值是否为NULL. - 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。