学习嵌入式的第十九天——Linux——文件编程

标准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 * 指针

相关推荐
陈年老古董19 分钟前
OpenCV 人脸识别学习笔记:从Haar检测到三种特征脸算法实战
笔记·opencv·学习·人脸识别
旖旎夜光24 分钟前
【LangChain实战】LangChain 学习笔记(二):结构化输出、流式传输与消息管理
人工智能·笔记·python·学习·ai·langchain
我是你的开心果7781 小时前
ai全栈应用开发学习day19
学习
是隼人1 小时前
buuctf-pwn wustctf2020_closed(文件描述符)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
励志不掉头发的内向程序员1 小时前
【LibreCAD 2D架构】从两个坐标到图形实体:RS_ActionDrawLine如何创建RS_Line
开发语言·c++·qt·学习·系统架构
sunshine22 girl2 小时前
Java学习一 环境配置1 安装JDK,配置环境变量
java·开发语言·学习
我爱cope2 小时前
【计算机网络 | 传输层5:TCP 如何实现可靠传输?滑动窗口、累计确认与重传机制】
网络·网络协议·学习·tcp/ip·计算机网络·传输层
zfoo-framework2 小时前
kotlin技术栈各种 学习文档
学习
是隼人2 小时前
buuctf-pwn wdb_2018_3rd_soEasy(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
mykj155110 小时前
英语单词APP解锁学习新方式,智能高效背单词
学习·英语单词app