步骤:打开、读取、关闭
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
int main()
{
FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test.txt", "r");
if (pf == NULL)
{
perror("fopen ERROR");
return 1;
}
// 读取
//fopen(pf);
// 关闭
fclose(pf);
return 0;
}
注意:1. 文件路径中,必须是双\,且mode选的"r",目录下要有text文件,没有则会报错。但是如果选择"w"模式,则会创建
2. 先判断了是否打开这片区,下面才是读取
3: 文件使用方式:r、w、a:只读、只写、追加
3. 写文件案例:利用fputc():针对所有输出流,fgetc()针对所有输入流
分析:必然是w模式,且写入用fputc()函数
int main()
{
FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test_write.txt", "w");
if (pf == NULL)
{
perror("fwrite ERROR");
return 1;
}
char ch = 'a';
for (;ch<='z'; ch++)
{
fputc(ch, pf);
}
// 读取
//fopen(pf);
// 关闭
fclose(pf);
return 0;
}
4. 读文件案例:利用fgetc(),遇到末尾或者错误,会返回EOF,所以以EOF判断
int main()
{
FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test_write.txt", "r");
if (pf == NULL)
{
perror("fwrite ERROR");
return 1;
}
/*char ch = 'a';
for (;ch<='z'; ch++)
{
fputc(ch, pf);
}*/
// 读取
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}
// 关闭
fclose(pf);
pf = NULL;
return 0;
}
5 流:外部设备不一样,操作外部设备读写方法也不一样,把字符都放在流中,程序员关注从流中读写,不用在意外部设备,其实上面pf就是流。
stdin、stdout、stderr:C程序运行起来,这三个流默认是打开的
在和不同外设交互时这些流都有用
单个读、单个写:都用fgetc、fputc
stdin针对所有输入流,stdout针对所有输出流
示例代码:
int ch = fgetc(stdin);
fputc(ch, stdout);
单行读、单行写:fputs、fgets,如果要换行,加上\n
FILE* pf = fopen("test1.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写一行
fputs("qwerty", pf);
// 关闭
fputs("abcdef", pf);
return 0;
}
结果:
没有换行,写入的时候,需要加\n
· 按一行行重复读取:while:fgets返回不为空
多行读取:需要接收的字符数组,接收长度,文件流
char arr[256] = { 0 };
while (fgets(arr, 256, pf)!=NULL)
{
printf("%s", arr);
}
// 写文件
fprintf(pf, "%s %d %lf", s.name, s.agem, s.d)
// 关闭文件
fclose(pf)
pf = NULL;
return 0;
如上,实现了结构体中内容存入了文件,下面实现从文件中读取到结构体中
注意是百分号爱了F,不是单纯F,是LF,代表double
// 读文件 name是数组,名字就是地址,age和d是变量,需要取地址
struct stu
{
char name[20];
int age;
double d;
};
struct stu s = {0};
FILE* pf = fopen("test1.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 写文件
//fprintf(pf, "%s %d %1f", s.name, s.age, s.d);
// 读文件 name是数组,名字就是地址,age和d是变量,需要取地址
fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
// 打印:
printf("%s %d %lf\n", s.name, s.age, s.d);
// 关闭
fclose(pf);
pf = NULL;
return 0;
}
总之,先读出来,再打印,也可以用fprintf,给stdout
fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
// 打印:
//printf("%s %d %lf\n", s.name, s.age, s.d);
fprintf(stdout, "%s %d %lf\n", s.name, s.age, s.d);
// 关闭
所以说,fprintf()可以用在打印文件内,也可以用来输出到文件中
sprintf、sscanf的使用
sprintf把结构体数据存入字符串中,sscanf可以从读取字符串中数据到结构体
示例
char buf[256] = { 0 };
struct S s = { "zhangsan", 20, 95.5 };
struct S tmp = { 0 };
sprintf(buf, "%s %d %lf", s.name, s.age, s.d);
printf("%s\n", buf);
sscanf(buf, "%s %d %lf", tmp.name, &(tmp.age), &(tmp.d));
printf("%s %d %lf", tmp.name, tmp.age, tmp.d);
从输入流读字符,再打印到输出流
fgetc和fputc适用于所有输入流和输出流
int ch = fgetc(stdin);
fputc(ch, stdout);
return 0;
以二进制形式写进去会乱码
张三以二进制和文本方式写,都是张三,但是数字以二进制形式,以文本形式打开,显示是乱码。
struct S s = { "张三", 20, 95.5 };
// 写文件,二进制方式 write_brinary
fopen("test3.txt", "wb");
FILE* pf = fopen("test3.txt", "wb");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
// 二进制方式写文件
fwrite(&s,sizeof(struct S), 1, pf);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
需以二进制方式读文件
int main()
{
struct S s = { "张三", 20, 95.5 };
// 写文件,二进制方式 write_brinary
fopen("test3.txt", "rb");
FILE* pf = fopen("test3.txt", "wb");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
// 二进制方式写文件
//fwrite(&s,sizeof(struct S), 1, pf);
// 二进制读文件
fread(&s, sizeof(struct S), 1, pf);
printf("%s, %d, %lf\n", s.name, s.age, s.d);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
这里发现,txt文件本来看着是乱码,现在读出来是正常情况。
不管是读还是写,第三个参数:1、2是最多读取几次
int main()
{
// 打开文件
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
// 随机写
// 正常读, 现在读到的是第一个字符
//int ch = fgetc(pf);
//printf("%c\n", ch);
// 随机读
fseek(pf, 3 SEEK_CUR);
int ch = fgetc(pf);
printf("%c\n", ch);
// 关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fseek中是3,表示从3开始,
发现读出来的是d,test文件中,我是abcde
所以运行结果是:
文件缓冲区的存在:
写文件,先写入缓冲区,刷新缓冲区,才将缓冲区文件,写入文件。