IO
input: 从磁盘读取数据到内存中
output: 把内存中的数据写入到磁盘上
1.文件
2.文件类型
3.文件IO和标准IO
对一个文件有两种不同的操作方式
-
文件IO------(linux系统提供)
系统调用:当我们的应用程序要使用一些底层的功能的时候,不应该自行访问底层,而应该向操作系统发出请求。特点:
- 不带缓冲区
- 操作系统直接提供的函数接口
- 调用系统调用是很耗费资源的
-
标准IO------(C库提供)
C库函数:在系统调用接口之上封装的接口,一个C库函数可以封装多个系统调用函数。
作用:- 增强了代码的可移植性,复用性
- 提高了效率。
标准IO增加了一个【缓冲机制】
EG:
4.标椎IO
[fopen/fclose/fgetc/fputc/fgets/fputs/fread/fwrite]
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
功能:打开文件
参数:
pathname: 文件的路径名
mode: 打开文件的方式
r: 以只读的方式打开文件,文件已存在
r+ : 以读写的方式打开文件,文件已存在
w: 以可写的方式打开文件,文件已存在,则清空文件的内容
文件不存在,则创建一个文件
w+: 以读写的方式打开文件,文件已存在,则清空文件的内容
文件不存在,则创建一个文件
a: 以可写的方式打开文件,文件存在,追加内容在末尾
a+: 以读写的方式打开文件,文件存在,追加内容在末尾
返回值:
成功: FILE * 流指针 本质上是一个结构体指针
失败: NULL
*FILE fp = fopen(“./1.txt”, “w+”);
cd ~
sudo apt install ctags
sudo ctags -R
建立索引
使用:
vim -t FILE
敲空格,直到输入数字为止,然后输入4,敲回车
光标移到结构体名, ctrl + ] , 跳转过去, 输入1, 敲回车
就看到了结构体的内容
FILE:系统会自动为使用的文件在内存中开辟一片空间,来存储该文件的详细信息,这个空间类型为 FILE 结构体类型,该结构体由系统设计。
FILE *:流指针,在标准IO中,每次成功打开一个文件,都会返回一个流指针,这个流指针就描述了一个文件,所有的标准IO都围绕流指针来进行。
//出错处理
strerror(errno); //参数就是错误码errno
perror(“fopen”); //参数就是字符串
同一个文件,可以存在多个流指针,与之对应。
示例:利用标椎IO函数测试当前系统最大能打开的文件个数。
1021+3 = 1024
stdin :标椎输入流
stdout:标准输出流
stderr:标准错误流
#include <stdio.h>
int fclose(FILE *stream);
功能: 关闭流指针
参数: 流指针
fclose(fp);
为什么要关闭一个文件?
一、防止其他进程操作这个文件
二、释放结构体占用的资源
在程序结束时,系统自动回收资源(不完全),所以尽量写上fclose。
系统默认打开了3个流指针
stdin (标准输入,终端进行输入)
stdout(标准输出,终端打印出来)
stderr(标准错误,终端打印出来)
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
功能: 改变流指针的方向
参数:
pathname:文件的路径名
mode:打开文件的方式 "r" "r+" "w" "w+" "a" "a+"
stream: 流指针
#include <stdio.h>
int fgetc(FILE *stream);
功能:读取一个字节的数据
参数:
流指针
返回值:
成功: ascii值
失败: -1
#include <stdio.h>
int fputc(int c, FILE *stream);
功能:写入一个字节的数据
参数:
c: 一个字节
stream:流指针
返回值:
成功: ascii值
失败: -1
void rewind(FILE *stream);
功能:将文件指针移到文件的开头
参数: 流指针
int feof(FILE *stream)
功能:测试给定流 stream 的文件结束标识符。
参数:
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
返回值
当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。
每一个终端都是一个文件: pts/xxx 这个就是终端对应的文件,这个文件的名字是以数字命名的
这个文件存储在 : /dev/pts/xxx
这些文件是由linux系统自动创建。当打开一个终端时,就会重建一个新的文件与之对应
stdin、stdout、stderr都指向的是同一个文件(终端文件)。
示例:直接向终端写入’x’
ps :查看当前终端运行的进程
FILE
struct _IO_FILE{
char *_IO_buf_base;
char *_IO_buf_end;
int _fileno;
};
[缓冲区: 行缓存、无缓存、全缓存]
printf、stdin 、stdout是行缓存,缓冲区大小是 1024byte == 1Kbyte
//1.行缓存满了 或遇到’\n’输出条件
//2.fflush可以强制刷新 (fflush)
//3.文件关闭的时候 fclose(stdout)
//4.程序结束的时候exit return
#include <stdio.h>
int fflush(FILE *stream);
功能:强制刷新流指针
参数:流指针
无缓存:stderr
全缓存:通过fopen函数打开的流指针,这个流指针fp的缓冲区大小是 4*1024 4Kbyte
//1.缓存区满
//2.fclose(fp)
//3.return
//4.exit
//5.fflush(fp)
char *fgets(char *s, int size, FILE *stream);
功能:读取一行的数据,存到s中
参数:
s:内存地址 char s[];
size: 读取的字节数 size-1
stream: 流指针
返回值:
成功:s
失败:NULL
注意:这里的一行,是指 size-1 或者 '\n'
读到文件的末尾,返回NULL
练习:文件有多少行?
int fputs(const char *s, FILE *stream);
功能:把内存中的数据写入到流指针指向的文件中
参数:
s :内存地址 char s[];
stream: 流指针
返回值:
成功:非负值
失败:-1
写入"hello world"
示例:从标椎输入(stdin)得到字符串 写入到 文件当中
练习:复制文件
int fseek(FILE *stream, long offset, int whence);
功能:定位文件指针
参数:
stream: 流指针
offset: 偏移量
+100 :向后偏移100个字节
-100 :向前偏移100个字节
whence: 基点
SEEK_SET 文件开头
SEEK_END 文件末尾
SEEK_CUR 文件当前的位置
返回值:
成功:0
失败:-1
定位到文件末尾: fseek( fp , 0 , SEEK_END );
定位到文件末尾的前一个字节:fseek( fp , -1 , SEEK_END );
long ftell(FILE *stream);
功能: 返回文件指针到文件开头的长度
获取文件大小
作业:查单词
流程:
1.打开文件
- 循环
- 输入一个单词
- 遍历文件
- 打印出单词信息
- 重新开始查询
- 关闭文件
fset, int whence);
功能:定位文件指针
参数:
stream: 流指针
offset: 偏移量
+100 :向后偏移100个字节
-100 :向前偏移100个字节
whence: 基点
SEEK_SET 文件开头
SEEK_END 文件末尾
SEEK_CUR 文件当前的位置
返回值:
成功:0
失败:-1
定位到文件末尾: fseek( fp , 0 , SEEK_END );
定位到文件末尾的前一个字节:fseek( fp , -1 , SEEK_END );
```c
long ftell(FILE *stream);
功能: 返回文件指针到文件开头的长度
获取文件大小