标准IO
进一步认识标准io:
1975 Dennis r IO库,
从C语言的标准,ANSI c
IO input output
I: 键盘是标准输入设备 ====》默认输入就是指键盘 /dev/input
O: 显示器是标准输出设备 ==》默认输出就是指显示器
Linux操作系统当中IO都是对文件的操作
C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
标准IO在UNIX上是对文件IO的封装
一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,
加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源
说明:
标准IO库,不单单是linux上有,在windows,Mac os上都有。
很多操作系统都实现了标准IO库。
都是依据IOS C标准实现的。
所以基本保证了可移植性。
但是因为标准和具体实现之间的差异,
未必敢保证所有的函数在都可以相互通用。
标准IO都干了些啥?
标准IO处理了很多细节:
(1).处理缓冲区分配 (缓存–提高效率 — 慢速 快速)
(2).读写IO的块长度的优化
(3).对系统调用进行了封装,内部对应的"文件描述符"
好处:
用户使用方便,不必再担心如何选择正确的块长度
地位:
标准I/O库是由Dennis Ritchie在1975年左右编写的。
它是Mike Lesk编写的可移植I/O库的主要修改版本。
令人惊讶的是,35年来,几乎没有对标准I/O库进行修改。
定位函数 fseek() ftell() rewind()
int fseek(FILE *stream, long offset, int whence);
功能:
将stream指定的文件,从whence位置,定位到offset的位置
参数:
@stream — 表示要定位的文件
@offset — 偏移量
>0 //需要考虑参考点是否可以
<0 //可以小于0,也需要看参考点
@whence — 参考点
SEEK_SET //文件开头
SEEK_CUR //文件当前位置
SEEK_END //文件结尾
返回值:
成功 0
失败 -1 && errno会被设置
fseek(fp,0,SEEK_SET); //定位到开头
fseek(fp,0,SEEK_END); //定位到开头
fseek(fp,100,SEEK_SET);//从头往后 偏移 100个字节
fseek(fp,-100,SEEK_SET);//从头往后 偏移 100个字节
说明:
文件往后偏移量 如果大于 文件本身是可以的
如果想占有存储空间,必须要有写操作
多出来的空间 — 空洞 — 用'\\0'
long ftell(FILE *stream);
获得stream对应文件的当前位置指示器的值
eg:
//文件大小
fseek(fp,0,SEEK_END);
long len = ftell(fp);
void rewind(FILE *stream);
功能,将文件定位到开头
空洞文件
创建空洞文件步骤:
1.定位 偏移
2.做一次写操作
如百度云之类的,从上面下载文件都会先创建空洞文件提前抢占磁盘空间,如果空间不足可以提前提醒,减少时间的损耗
缓存区
缓存的设计原则:
1.与终端关联的设备 —行缓存
2.普通文件 —全缓存
3.出错处理 —不缓存
行缓冲
1k, terminal,主要用于人机交互stdout,多用于与客户有互动
行缓存多是关于终端的一些操作
刷新条件:
1.遇到\\n刷新
2.缓存区满刷新
3.程序正常结束刷新
4.fflush刷新 fflush(stdout);
全缓冲
4k,主要用于文件的读写
对普通文件进行标准IO操作,建立的缓存一般为全缓存
刷新条件:
1.缓存区满刷新
2.程序结束刷新
3.fflush来刷新 fflush(fp);
输出重定向
./a.out > 1.txt //把a.out运行的结果输出到1.txt中
无缓冲
0k 主要用于出错处理信息的输出 stderr
不对数据缓存直接刷新
标准IO小结
库函数和系统调用
1. 库函数最终还是借助系统调用来实现
库函数
优点:
更丰富的功能
更优化的处理
方便高效
缺点:
安全性
系统调用
优点:
简单
安全性
缺点:
功能不够丰富
使用起来不大方便
文件IO
open
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能:
打开文件
参数:
@pathname — 文件名
@flags
必选:
O_RDONLY
O_WRONLY
O_RDWR
附加:
O_APPEND //追加 —写
O_CREAT //创建
O_TRUNC //截断
@mode
表示创建文件的权限 — 只有前面有O_CREAT时,才需要指定
0777
0666
实际的文件权限:
mode & ~umask
返回值:
成功 返回文件描述符
失败 -1 &&errno
与fopen的关系
close
close(文件描述符)
关闭一个文件,并且使该文件描述符可以重复使用
read
ssize_t read(int fd, void *buf, size_t count);
功能:
从fd对应文件中读取数据,读count个字节,存放到buf指定的一块空间
参数:
@fd 就是要读取的文件
@buf 存放数据的空间
@count 要读取的字节数
返回值;
成功 读取到的字节数
失败 -1 &&errno
注意:
read读到的数据,如果要当作字符串处理,
注意,需要手动处理成字符串 ,即手动加'\\0'
write
ssize_t write(int fd, const void *buf, size_t count);
功能:
从buf中获得数据,写count个字节到 fd对应文件中
参数:
@fd 就是要写的文件
@buf 存放数据的空间
@count 要写入的字节数
返回值;
成功 写入的字节数
失败 -1 &&errno
lseek
lseek
off_t lseek(int fd, off_t offset, int whence);
功能:
将fd定位到从whence开始的offset的位置
参数:
@fd 文件
@offset 偏移量
@offset — 偏移量
>0 //需要考虑参考点是否可以
<0
@whence — 参考点
SEEK_SET //文件开头
SEEK_CUR //文件当前位置
SEEK_END //文件结尾
定位开头:
lseek(fd,0,SEEK_SET);
定位到末尾
lseek(fd,0,SEEK_END);
返回值:
成功 返回从文库开头到当前定位处的偏移量
失败 -1 && errno
//获得文件大小
off_t len = lseek(fd,0,SEEK_END); //off_t 是一个long int型
流指针与文件描述符的转换
int fileno(FILE *stream); //将FILE *fp 流指针转换为 fd
fd —> FILE *fp
FILE *fdopen(int fd, const char *mode);
功能:
将 fd 对应文件打开 关联一个 FILE * 指针
评论前必须登录!
注册