对文件进行操作前后
一般需要做的工作如下:
int main()
{
//像如下详细的路径就是绝对路径
//若在当前文件的同一层,可以使用相对路径
//若在上一层,则前面加../如../test.txt,再上一层再加
FILE* pf = fopen("F:\bit\bit_online_code\bit_online_code\test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
else
{
printf("打开文件成功");
}
//读文件
//...
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件的打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的 关系。
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。
FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );
打开方式如下:
文件使用方式 | 含义 | 如果指定文件不存在 |
---|---|---|
“r”(只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
“w”(只写) | 为了输出数据,打开一个文本文件 | 建立一个新的文件 |
“a”(追加) | 向文本文件尾添加数据 | 出错 |
“rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
“wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
“ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
“r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,建议一个新的文件 | 建立一个新的文件 |
“a+”(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
“rb+”(读写) | 为了读和写打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
“ab+”(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
实例代码:
/* fopen fclose example */
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","w");
if (pFile!=NULL)
{
fputs ("fopen example",pFile);
fclose (pFile);
}
return 0;
}
文件的顺序读写:
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
for (char i = 'a'; i <= 'z'; ++i)
{
fputc(i, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
int ch = fgetc(pf); //注意返回的是ascii
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件,写一行
fputs("hello world\n", pf);
fputs("hello bit", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件,读一行
char buf[20] = { 0 };
fgets(buf, 5, pf); //真正读的是四个,有一个空间为/0
puts(buf);
fgets(buf, 20, pf); //一行不够20个就不继续往下读了
puts(buf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "zhangsan", 20, 95.5 };
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//格式化写入文件
fprintf(pf, "%s %d %f\n", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
int main()
{
struct S s = { 0 };
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//格式化读取文件
fscanf(pf, "%s%d%f", s.name, &s.age, &s.score);
//打印
printf("%s %d %f\n", s.name, &s.age, &s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
C语言不需要管如何将数据放在各种各样的输出设备中
只需要把数据放在流中
任何一个C语言程序打开时,默认打开三个流:
- stdin - 标准输入 FILE*
- stdout - 标准输出 FILE*
- stderr - 标准错误 FILE*
int main()
{
int ch = fgetc(stdin);
fputc(ch, stdout);
return 0;
}
int main()
{
struct S s = { 0 };
fscanf(stdin, "%s %d %f", s.name, &s.age, &s.score);
fprintf(stdout, "%s %d %f\n", s.name, s.age, s.score);
return 0;
}
struct S
{
char name[20];
int age;
float score;
};
//测试二进制的写:fwrite
int main()
{
struct S s = { "张三", 20, 98.5 };
FILE* pf = fopen("test.txt", "wb"); //二进制读写用只读和只写:rb, wb
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
fwrite(&s, sizeof(struct S), 1, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//测试二进制的读:fread
int main()
{
struct S s = { 0 };
FILE* pf = fopen("test.txt", "rb"); //二进制读写用只读和只写:rb, wb
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
fread(&s, sizeof(struct S), 1, pf);
printf("%s %d %f\n", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "zhangsan", 20, 98.5 };
char buf[100] = { 0 };
sprintf(buf, "%s %d %f", s.name, s.age, s.score);
printf("%s\n", buf);
struct S tmp = { 0 };
sscanf(buf, "%s %d %f", tmp.name, &tmp.age, &tmp.score);
printf("%s %d %f\n", tmp.name, tmp.age, tmp.score);
return 0;
}
scanf - 从键盘上读取格式化的数据 - stdin
printf - 把数据输出到屏幕上 - stdout
fscanf - 针对所有的输入流的格式化的输入函数 stdin, 打开的文件。。。
fprintf - 针对所有输出流的格式化的输出函数 stdout,打开的文件。。。
sscanf - 从一个字符串中还原一个格式化的数据
sprintf - 把一个格式化的数据转换成一个字符串
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
else
{
int ch = fgetc(pf);
printf("%c\n", ch); //a
ch = fgetc(pf);
printf("%c\n", ch); //b
ch = fgetc(pf);
printf("%c\n", ch); //c
//此时不想继续读d
//想去读b
fseek(pf, -2, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, 1, SEEK_SET);
ch = fgetc(pf);
printf("%c\n", ch);
printf("%d\n", ftell(pf)); //告诉此时相对起始位置偏移量
rewind(pf);
ch = fgetc(pf); //让光标回到起始位置
printf("%c\n", ch);
}
return 0;
}
文件缓冲区
#include<Windows.h>
//vs2022 win11环境测试
int main()
{
FILE* pf = fopen("test.txt", "w");
fputs("abcdef", pf);
printf("睡眠10秒 - 已经写数据了,打开test.txt文件,发现没有内容");
Sleep(10000);
printf("刷新缓冲区\n");
fflush(pf);
printf("再睡眠10秒 - 此时打开test.txt文件,文件有内容了");
Sleep(10000);
fclose(pf);
//注:fclose在关闭文件的时候,也会刷新缓冲区
pf = NULL;
return 0;
}