前言:C语言程序运行时,它的数据存储在内存中一旦,程序终止其数据就会丢失,若想保留数据应该将数据存储在文件(磁盘)中。
流:
每次运行c语言程序时,都会默认给我们打开
标准输入流(stdin):c语言程序能读取我们从键盘中输出的数据
标准输出流(stdout): 能将数据打印到显示器上
如何将数据存储进文件呢?
文件的属性有一个FILE类型的结构体来描述,通过一个FILE 类型的指针可以通过控制文本信息区来改变文件。
1.fopen 和 fclose
1.1 fopen
filename:文档的名称
mode:打开文件的方式
"r" :只读,若在源文件所在的目录下没有相应的文件,就会报错。
"w" : 只写,若在源文件所在的目录下没有相应的文件,就会创建一个。
原文件所在目录下的所有文件:
若用只读的形式打开文件并且该目录下没有相应的文件:
fopen会返回NULL并报错
若用只写的形式打开文件并且该目录下没有相应的文件:
会创建data.txt 着个文件
1.2 fclose
这里可以类比动态内存申请,最后需要释放申请的空间并将指针置为 NULL
而关闭文件也类似
//释放空间
free(p);
p = NULL;
//关闭文件
fclose(pf);
pf = NULL;
2. 文件内容顺序读写
这里会介绍
fgetc | 从输入流中读一个字符 |
fputc | 向输出流中写一个字符 |
fgets | 从输入流中读一串字符 |
fputs | 向输出流中写一串字符 |
fprintf | 向文件中写格式化的数据 |
fscanf | 从文件中格式化读数据 |
fwrite | 向文件中以二进制的形式写入数据 |
fread | 将文件中二进制形式的数据以文本的形式读出 |
2.1 fputc
character:想要写入的数据,若是字符会将其转换为对应的ASCII值
stream:将数据传入stream所指向的文件中
返回值(int):若写入成功则返回相应的 int 类型的值 ; 若失败,则返回 EOF(-1)
2.2 fgetc
stream:从stream所指向的文件中读一个字符
返回值(int):若读取成功则返回读取的数据所对应的 int 类型的值,当读到文件末尾或读取错误时 fgetc 会返回 EOF(-1)
2.3 fputs
同fputc差不多
str:指向想要写入的字符串
返回值:若写入成功,返回一个非负的数;若失败,则返回 EOF
2.4 fgets
介绍:将stream所指向的文件的(num-1)个字符读入str所指向的空间中
为什么是(num-1)个?
是因为第num个是 '\0'
返回值:若读取成功则返回 str ;若失败则返回NULL
2.5 fprintf
作用将格式化的内容写进文件中。
这里于printf做对比:
fprintf使用方式与printf一样就是多了一个参数:stream ,就是将格式化内容输出到文件中;而printf是将格式化内容输出到显示器(stdout标准输出流)上。
代码:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//使用
fprintf(pf, "%d %s %c", 12, "hello world", 'b');
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
运行结果:
2.6 fscanf
作用:从文件中格式化的读出数据
用法与scanf差不多
示例代码:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//使用
int a;
char str[20];
char b;
//读取数据
fscanf(pf, "%d %s %c",&a,str,&b);
printf("%d %s %c", a, str, b);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
图解:
扩展:sprintf 和 sscanf
作用:将格式化的数据写进字符串
作用: 从字符串中读取格式化的数据
使用代码:
#include <stdio.h>
int main()
{
int a = 10;
char b = 'x';
char str[20] = { 0 };
sprintf(str, "%d %c", a, b);
printf("%s\n", str);
int c;
char d;
sscanf(str, "%d %c", &c, &d);
printf("%d %c\n", c, d);
}
运行结果:
2.7 fwrite
简介:将ptr指向的 count个 大小为size字节的数据 ,以二进制的形式写入stream中
使用代码:
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
FILE* pf = fopen("test.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int count = sizeof(arr) / sizeof(int);
fwrite(arr, sizeof(int), count, pf);
fclose(pf);
pf = NULL;
return 0;
}
test.txt 文件:
2.8 fread
从文件中将二进制数据读到ptr所指向的空间中,参数与fwrite相同。
返回值:返回成功读取的数据的个数,如果读到文件的末尾返回0。
对2.7的test.txt 输出
代码:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int count = sizeof(arr) / sizeof(int);
fread(arr, sizeof(int), count, pf);
for (int i = 0; i < count; i++)
{
printf("%d ", arr[i]);
}
fclose(pf);
pf = NULL;
return 0;
}
//另一种写法:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int i = 0;
while (fread(&arr[i], sizeof(int), 1, pf) != 0)
{
printf("%d ", arr[i]);
i++;
}
fclose(pf);
pf = NULL;
return 0;
}
运行结果:
3.文件内容的随机读写
3.1fseek
作用:将文件指针从origin的位置偏移 offset 个字节
offset:偏移量
origin:表示文件指针的起始位置
SEEK_SET:文件的开头
SEEK_CUR:文件当前的文件指针的位置
SEEK_END :文件的末尾
使用代码:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fseek(pf, 2, SEEK_SET);
fputs("hello world", pf);
fclose(pf);
pf = NULL;
return 0;
}
写入test.txt 的文件的数据
3.2 ftell 和 fwind
返回值:文件指针现在的位置相对于起始位置的偏移量
使文件指针重新指向文件的开头
两个函数结合使用的代码:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//先偏移 3 个字节
fseek(pf, 3, SEEK_SET);
long cur = ftell(pf);
printf("%ld\n", cur);
rewind(pf);//再是文件指针重新指向文件开头
cur = ftell(pf);
printf("%ld\n", cur);
return 0;
}
运行结果:
4.文件读取结束的判断标志
文件读取结束的情况:
1.读到文件末尾(feof可以判断)
2.读取错误(ferror可以判断)
4.1 feof
判断是否是读到文件末尾而结束,如果是则返回一个非0的数;否则返回0.
示例:
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
if (feof(pf))
{
printf("读到到文件末尾\n");
}
else
printf("未读到文件末尾\n");
fclose(pf);
pf = NULL;
}
4.2 ferror
判断是否是读取错误,如果是返回非0 的数;如果不是就返回0.
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fputc('a', pf);
if (ferror(pf))
{
printf("发生读取错误\n");
}
else
printf("未发生读取错误\n");
fclose(pf);
pf = NULL;
}
发生错误的原因:因为这里是以只读的形式打开文件,而代码中用了fputc,所以读取错误。
5.文件缓冲区
每次c语言程序从文件中读数据或向文件中写数据时,都会经过文件缓冲区,等文件缓冲区被数据塞满时回向另一端输出,或刷新缓冲区,将缓冲区的数据输出,就比如fclose 完就会刷新缓冲区,未刷新缓冲区时,数据就存储在缓冲区。
等程序自y结束时也会刷新缓冲区。
结语:
洋洋洒洒写了4000字,我真是太狂喽!哈哈哈,开玩笑,我的c基础快学完了。祝大家学业有成。
标签:文件,fopen,return,4000,int,pf,操作,NULL From: https://blog.csdn.net/2402_82658387/article/details/136987638