编写程序的时候,我们可以通过各种设备(如键盘、U盘等)获得数据,当然我们也可以通过各种设备输出相应的数据到它们当中去,可程序与设备进行了怎样的操作才实现了数据的输入输出呢?显然,这里面的水太深了! 一 一弄懂将会花费许多精力,所以 为了方便对各种设备的操作, 我们抽象出 “流” 的概念。
流, 可以理解为 程序 与 各种设备 之间的 纽带 ,通过这条纽带,程序与各种设备之间联系紧密, “程序的话设备听得懂,设备的话程序听得懂”, 即 流 完成了 程序与设备之间 数据输入或输出是怎样联系的操作。
至于到底是怎样完成的,感兴趣的朋友还请自己查阅资料了解, 编写程序的时候,我们只要清楚,实现 程序与设备之间 数据 的输入与输出, 需要进行有关 流 的操作
具体操作就是: 1.打开流,2.进行输入或者输出,3.关闭流
打开流,是为了实现有效的输入输出
关闭流,是为了确保资源正确管理、数据完整性和避免潜在错误等。
你可能会想:what? 我最开始写程序的时候可是没对 任何流 进行 任何的操作,就能实现键盘输入数据、数据显示在终端的操作。 事实上,c语言在程序启动时, 默认打开了3流:
在大多数情况下,stdin
与键盘输入相关联,但也可以通过重定向或管道从文件或其他程序获取输入。
在大多数交互式程序中,stdout
与显示器(通常是屏幕)相关联,但输出也可以被重定向到文件或其他输出流中。
stderr
的输出在默认情况下是发送到显示器的,但它在某些情况下可以被单独重定向或处理。
------------------------------------------------------------------------------------------------------------------------
这三种流,都是在stdio.h
头文件中定义
当默认打开了这三个流,我们就可以使用scanf 、 printf 函数实现输入输出操作了
stdin 、 stdout 、 stderr 三个流的类型是 FILE* , 通常被称为 文件指针
c语言中, 就是通过 FILE* 的文件指针来维护流的各种操作的
(1)缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
(2)当程序对文件进行操作时,系统会在内存中为该文件开辟一个 文件信息区
这个文件信息区用于存放文件的各种信息,如文件名、文件大小、文件位置、文件状态等。
文件信息区是一个结构体类型的变量 由系统声明, 取名 FILE
(3)不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。至于信息是怎样被填充的感兴趣的朋友还请自己去查资料了解
当我们创建一个FILE* 的指针变量之后 就能够访问该文件啦!
FILE* pf;//文件指针变量
(1)文件在读写之前应该 先打开 ,使用结束之后 再关闭
打开, 是为了实现读写操作
关闭,是为了释放系统资源、确保数据完整性、避免文件锁定和冲突、符合编程规范以及防止文件句柄泄漏等
(2)编写程序,打开文件的同时,会返回一个FILE*类型的指针变量指向该文件,相当于建立了指针与文件之间的关系
(3)C语言标准规定了使用fopen
函数来打开文件,以及使用fclose
函数来关闭文件。
-------------------------------------------------------------------------------------------------------------------
I 从左往右传入的第一个参数是 文件名,用引号括起来 此时文件名至少包括主干及后缀
如果不写路径,该函数就只会在当前工作目录(程序运行时的目录)下寻找
(1)加入路径时 \ 应该 使用 \\ ,这是为了转义字符的出现
C:\\Users\\D2407\\OneDrive\\ドキュメント\\雷军.docx
(2) . 表示当前目录, .. 表示当前目录的上一级目录, 所以为了省事,路径也可以写作
.\\ .. \\text.txt 表示当前目录的上一级目录的 test.txt文件
II第二个参数是 文件打开模式,也用引号括起来
以下是文件打开模式表:
模式 | 描述 | 文件不存在时 | 文件存在时 | 文件指针初始位置 | 内容是否被清空 |
---|---|---|---|---|---|
"r" | 以只读方式打开文件 | 打开失败 | 可读 | 文件开头 | 不清空 |
"w" | 以写入方式打开文件 | 创建文件 | 可写(覆盖) | 文件开头 | 清空 |
"a" | 以追加方式打开文件 | 创建文件 | 可写(追加) | 文件结尾 | 不清空 |
"r+" | 以读写方式打开文件 | 打开失败 | 可读写 | 文件开头 | 不清空 |
"w+" | 以读写方式打开文件 | 创建文件 | 可读写(覆盖) | 文件开头 | 清空 |
"a+" | 以读写方式打开文件 | 创建文件 | 可读写(追加) | 文件结尾 | 不清空 |
"rb" | 以二进制方式只读打开文件 | 打开失败 | 可读 | 文件开头 | 不清空 |
"wb" | 以二进制方式写入打开文件 | 创建文件 | 可写(覆盖) | 文件开头 | 清空 |
"ab" | 以二进制方式追加打开文件 | 创建文件 | 可写(追加) | 文件结尾 | 不清空 |
"rb+" | 以二进制方式读写打开文件 | 打开失败 | 可读写 | 文件开头 | 不清空 |
"wb+" | 以二进制方式读写打开文件(覆盖) | 创建文件 | 可读写(覆盖) | 文件开头 | 清空 |
"ab+" | 以二进制方式读写打开文件(追加) | 创建文件 | 可读写(追加) | 文件结尾 | 不清空 |
III
(1)成功打开文件,fopen 返回一个 指向 打开的文件流 的非空的FILE指针
可以使用这个指针来调用其他文件操作函数,如fread
、fwrite
、fgetc
、fputc
、fseek
等。
(2)打开失败,它就会返回NULL 。在这种情况下,你应该检查错误并采取适当的措施,如打印错误消息、退出程序等。
打印错误消息可用 perror 函数
perror
函数是 C 标准库中的一个实用函数,因为它会自动将错误代码(通常存储在全局变量 errno
中)转换为一个可读的错误消息。
-------------------------------------------------------------------------------------------------------------------
(1)传入的参数 stream
是一个指向 FILE
结构的指针,该结构代表了一个打开的文件流。这个指针必须是通过 fopen
、freopen
或 tmpfile
成功打开文件后返回的。
(2)
fclose
返回 0
。fclose
返回 EOF
(通常定义为 -1
),并设置全局变量 errno
以指示具体的错误类型。stream
指针将不再有效,不应再被用于任何文件操作。所以在调用 fclose
函数之后,将 stream
指针置空(即将它设置为 NULL
)是一个良好的编程习惯下面是代码实操 :
#include
int main()
{
//打开文件
FILE* pf;
pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("test.txt");//打印具体的错误原因
return 1; 返回非零值表示程序异常终止
}
//文件操作
fputs("举例子所用", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
程序无报错,成功创建文件并写入相关数据:
------------------------------------------------------------------------------------------------------------------------------
将只写,改为只读 : "w" --> "r"
#include
int main()
{
//打开文件
FILE* pf;
pf = fopen("test1.txt", "r");
if (pf == NULL)
{
perror("test1.text");//打印具体的错误原因
return 1; 返回非零值表示程序异常终止
}
//文件操作
fputs("举例子所用", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
当前目录下没有test1.txt 的文件,所以报错
关于 打开模式的其他操作 还请朋友们自己下去操练
点赞+关注 下期我们讲 关于文件操作的相关函数