文件(下)
目录
1。顺序读写函数
1.1 fputs
1.2fgets
1.3fprintf
1,4fscanf
1.5 sprintf
1.6 sscanf
1.7 fwrite
1.8 fread
2 ⽂件的随机读写
2.1 fseek
2.2 ftell
2.3 rewind
3 . ⽂件读取结束的判定
3.1 被错误使⽤的 feof
拷贝文件
ferror
4.⽂件缓冲区
书接下文上次我讲到
1。顺序读写函数
1.1 fputs
#include <stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror("fopen");
}
//写文件
fputs("are you ok?", pf);//fputs是输入字符串
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
当你运行完后依照昨天的步骤找到要写入的文件打开出查看
记事本中实现了。
1.2fgets
#incldue <stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
//读文件
char ch[20] = "xxxxxxxxxx";
fgets(ch,5, pf);
printf("%s", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.3fprintf
在先了fprint 的时候我们来了解一些它与printf的区别。
我们发现fprintf和printf只相差一个流 ,下面用代码来解释
#include <stdio.h>
int main()
{
char book[40] = "wedadf";
char name[20] = "ch ";
float price = 999.9f;
//打开文件
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror("fopen");
}
//写文件
fprintf(pf, "%s %s %.1f", book, name, price);//与printf的格式相仿,只是多加了流
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1,4fscanf
我们可以发现这个与上面的printf 和fprintf 相似,
#include <stdio.h>
int main()
{
char book[40] = "wedadf";
char name[20] = "ch ";
float price = 999.9f;
//打开文件
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
//读 文件
fscanf(pf, "%s %s %f", book, name, &price);//将记事本的内容写到了数组中
printf(" % s % s % f", book, name, price);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
1.5 sprintf
#include <stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
{
char arr[100] = { 0 };
struct S s = { "chnegyun",23,50.4f };
//将s中的数据转换成字符串,存放在arr中
sprintf(arr, "%s %d %.1f",s.name,s.age,s.score );//把结构体的成员放到arr中
printf("%s \n", arr);
return 0;
结构体的内容放到了arr中
1.6 sscanf
#include <stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
{
char arr[100] = { 0 };
struct S s = { "chnegyun",23,50.4f };
//将s中的数据转换成字符串,存放在arr中
sprintf(arr, "%s %d %.1f",s.name,s.age,s.score );//把结构体的成员放到arr中
//从arr中提取格式化数据,放在tmp中
sscanf(arr, "%s %d %f", s.name, &(s.age), &(s.score));
printf("%s %d %f ", s.name, s.age, s.score);
return 0;
}
打印结果
1.7 fwrite
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
当我们查看的时候就会出现错误的编码,因为这是二进制形式写到文件中
这个时候我们就得讲下个函数了fread
1.8 fread
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
可以发现fwrite 和fread 的参数是相同的。
#include <stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
//读取二进制信息写到文件中
{
//打开文件
struct S s = { "chenyun ",23,3.14 };
FILE* pf = fopen("text.txt","rb");
if (pf == NULL)
{
perror("fopen ");
return 1;
}
//写文件
fread(&s, sizeof(struct S), 1, pf);
printf("%s %d %f",s.name,s.age,s.score );
//关文件
fclose(pf);
pf = NULL;
return 0;
}
我们发现这个代码真的打印出来的
2 ⽂件的随机读写
2.1 fseek
根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。
int fseek ( FILE * stream, long int offset, int origin );=
#incldue <stdio.h>
int main()
{
//读取二进制信息写到文件中
//打开文件
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen ");
return 1;
}
//读文件
int ch = 0;
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
//fseek(pf, 4, SEEK_SET);
//ch = fgetc(pf);
//printf("%c\n", ch);
//关文件
fclose(pf);
pf = NULL;
return 0;
}
前两个就打印出来了,
2.2 ftell
返回⽂件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
#include <stdio.h
int main()
{ FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen ");
return 1;
}
//读文件
int ch = 0;
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, -1, SEEK_END);
ch = fgetc(pf);
printf("%c\n", ch);
printf("%d", ftell(pf));//文件有多少数字就会返回几
//关文件
fclose(pf);
pf = NULL;
return 0;
}
记事本中存放了5个字符,那么我们打印看一看结果。
如果我在记事本中增加字母,那么打印出来的数字也会随着增加。下面我们来实现一下。
这里就会增加。
2.3 rewind
让⽂件指针的位置回到⽂件的起始位置
回到了起始位
#include <stdio.h>
int main()
{ FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen ");
return 1;
}
//读文件
int ch = 0;
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, -1, SEEK_END);
ch = fgetc(pf);
printf("%c\n", ch);
printf("%d\n", ftell(pf));//文件有多少数字就会返回几
rewind(pf);// 重新想文件的位置回到起始位置 a
ch = fgetc(pf);
printf("%c\n", ch);
//关文件
fclose(pf);
pf = NULL;
return 0;
}
3 . ⽂件读取结束的判定
3.1 被错误使⽤的 feof
牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。 feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束
1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets)、fgetc 判断是否为 EOF .
• fgets 判断返回值是否为 NULL .
2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
• fread判断返回值是否⼩于实际要读的个数。
拷贝文件
将text 1 拷贝到text2 中
下面请看代码:
#include <stdio.h>
int main()
{
//打开文件
FILE* pfread = fopen("text1.txt", "r");
if (pfread == NULL)
{
perror("fopen");
return 1;
}
FILE* pfwrite = fopen("text2.txt", "w");//如果没有该文件 w 会自动创建一个
if (pfwrite == NULL)
{
perror("fopen ");
fclose(pfread);
return 1;
}
//读/写文件
int c = 0;
while ((c=fgetc(pfread)) != EOF)
{
fputc(c,pfwrite);
}
//关闭文件
fclose(pfread);
pfread = NULL;
fclose(pfwrite);
pfwrite =NULL;
return 0;
}
有了前面的理解,相信大家看这个这些代码应该都不陌生了。
#include <stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读/写文件
int c = 0;
while ((c = fgetc(pf)) != EOF)
{
printf("%c ", c);
}
int ret = feof(pf);
printf("%d \n", ret);
ret = ferror (pf);
printf("%d \n", ret);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
ferror
ferror 要这样使用
4.⽂件缓冲区
ANSIC 标准采⽤“缓冲⽂件系统” 处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为 程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输 ⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓 冲区的⼤⼩根据C编译系统决定的。
大家有兴趣的可以研究一下这个代码
#include <stdio.h>
#include <windows.h>
//VS2022 WIN11环境测试
int main()
{
FILE* pf = fopen("test.txt", "w");
fputs("abcdef", pf);//先将代码放在输出缓冲区
printf("睡眠10秒-已经写数据了,打开test.txt⽂件,发现⽂件没有内容\n");
Sleep(10000);
printf("刷新缓冲区\n");
fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到⽂件(磁盘)
//注:fflush 在⾼版本的VS上不能使⽤了
printf("再睡眠10秒-此时,再次打开test.txt⽂件,⽂件有内容了\n");
Sleep(10000);
fclose(pf);
//注:fclose在关闭⽂件的时候,也会刷新缓冲区
pf = NULL;
return 0;
}
到这里文件就结束了。我们的c语言也接近尾声了,