学习嵌入式的第十九天——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 * 指针

相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习