目录
1.打开文件
(1) 函数:fopen 是打开文件的函数
(2)描述+理解:
文件打开后,在内存会自动生成一个文件信息区(存文件的地址、名字等)
然后就有个文件指针(FILE*)指向这个文件信息区
这个文件信息区和文件相关联,文件变-文件信息区跟着变
这个文件信息区实际上是个结构体变量
该结构体是由系统定义的
注:testthefile.sac 是笔者自己命名的一个文件
eg:vs2013中由系统声明的文件信息区结构体
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
(3)代码段
#include<stdio.h>
int main()
{
//打开文件
FILE *pf = fopen("testthefile.sac", "r");
//fopen()函数返回 文件信息区的地址
//判断是否为空指针
if (pf == NULL)
{
perror("fopen");
return 1;
//文件操作
//----------------
//关闭文件
fclose(pf) ; //该函数关闭指针指向的那个文件
pf=NUll ; //把pf设为空指针
}
注:写操作文件的代码,都要有这4个步骤
"r” 可以修改。这里表示以“读的形式打开文件”
(4)打开文件的形式
2.文件名 (路径+名称+后缀)
一个文件要有一个唯一的文件标识以便识别和引用
(1)路径( 分为绝对路径和相对路径)
注:这里 "testthefile.sac" 是相对路径,该文件会放在.c文件放的那个路径底下
绝对路径:
D:\Users\29035\Documents\Visual Studio 2013\Projects\goodtea\goodtea\testthefile.sac
(2)名称
(3)后缀 (文件的格式)
注:记得去查看那里勾上文件拓展名
3.流 (输入输出流)
1)描述+理解
流:
- 信息从外部输入设备(键盘/硬盘里的文件/网络信息等等)向计算机内部(内存)里输入
- 信息从计算机内部(内存)输出到外部输出设备(屏幕/硬盘里的文件等)
像水流一样,信息内存和外部设备间流动
1.c语言中我们频繁的使用scanf() 和printf()来输入输出:
scanf() :从标准输入流(键盘)中读取数据,并存在变量中
printf():从标准输出流(屏幕)中输出指定内容
c语言程序,只要运行起来,默认打开三个流
stdin - 标准输入流 -键盘
stdout - 标准输出流 - 屏幕
stderr - 标准错误流 - 屏幕所以,我们不用手动打开。但是,对于其他输入输出流(eg:文件流),我们是需要手动打开的。
2) 我们平时scanf就能输入/printf就能输出 :
其实是因为默认打开了标准输入流 - 键盘 / 标准输出流 - 屏幕
对于非默认打开的流,我们只能手动打开了 eg:文件流
(3)理解:屏幕键盘等硬盘其实可以算作是文件
函数解释:在流(stream)里输入一个字符(character)
如图:这里表在标准输出流(stdout-屏幕)里输出一个字符
4.相关函数(复习专用)
从流中获取 字符 / 字符串: fgetc(字符) / fgets (字符串)
从流中写入 字符 / 字符串: fputc / fputs
格式化输入输出: fscanf (从流中输入) / fprintf(从流中输出)
以二进制输入输出: fread / fwrite
(1)
从(文件流)文件指针指向的文件那里获取一个字符
#include<stdio.h>
int main()
{
FILE *pf = fopen("testthefile.sac", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//fgetc 从一个文件流中获取一个字符 (文件中已有字符)
int a=fgetc(pf);
printf("从文件中获取的字符:%c\n", a);
//从键盘上获取一个字符
int b = fgetc(stdin);
printf("从键盘上获取的字符:%c\n", b);
//关闭文件
fclose(pf);
}
想要从文件流那里获取字符串呢? - fgets
(2)
mean: 从流(stream)中获取,输入到str指向的空间。获取个数为 [ 0~num ) 左闭右开
可见:最多读6个(num-1)
#include<stdio.h>
struct S
{
char arr[10];
int num;
float sc;
}s;
int main()
{
FILE *pf = fopen("testthefile.sac", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//输入
fscanf(pf, "%s %d %f", s.arr, &(s.num), &(s.sc));
//从(文件流)pf指向的文件那里读入数据,放到结构体的成员变量里
//输出
fprintf(stdout, "%s %d %f", s.arr, (s.num), (s.sc));
//从标准输出流(屏幕)输出,放到结构体的成员变量里
//关闭文件
fclose(pf);
}
fscanf 和 scanf 区别:
1.scanf 默认是从标准输入流(键盘)输入
2.fscanf 第一个参数 是给 程序员 自己选择 输入的那个流。
本图是文本流。
也可以把 pf 改成stdin ,则是从标准输入流(键盘)中输入
3.fscanf 的其他参数和scanf一样,用法也是一样的
(3)以二进制写入
)
描述:从(stream)流中写入,把结构体变量ss的内容写入流(文件流)中
打开文件看到里面的内容看不懂,因为是以二进制的形式写入的
只要在以二进制的形式读入,我们就能知道内容是什么了
(4)以二进制读
描述:在pf(文件流)里读,读1次(1个元素),每次(每个元素)读取sizeof(struct S)个字节,把读出来的内容放在结构体变量sss中
第二个参数表示:每个元素的所占的空间
第三个参数表示:输入的元素个数
- 如果是把文件里存的通讯录输入到内存中,可以用数组接收,有几个联系人输入的元素个数就是几
以fwrite(二进制写入) 写入就以fread(二进制读)读,最终得出的数据确实和结构体变量ss一样
5.文件的随机读写
6.文件读取结束的判定:被错误使用的feof
7.文件缓冲区