LinuxC语言文件i/o笔记(第十八天)

文件i/o

标准i/o的特点是,其使用ANSI C标准(即标准c语言),文件i/o为POSI X标准(系统文件规范),前者带有缓冲区,为流------FILE,后者不带缓冲区,为文件描述符------fcl。

在linux下,标准i/o是基于文件i/o实现的。

使用的头文件为<unistd.h>

文件描述符:

每个打开的文件都对应一个文件描述符,

其不为负,linux系统里每打开一个文件都会自动分配一个文件符。

文件i/o通过文件描述符对文件进行操作(标准i/o的输入输出流)。

文件打开:

使用函数open:

int open(const char *path,int oflag,...);

第一个参数为文件名称(地址),第二个为打开的参数(后续讲),第三个就是文件若要建立的权限(使用8进制描述)。

成功返回文件描述符,失败返回EOF。

oflag的参数:

与标准i/o相似,也有只读读写什么的:

O_ RDONLY:只读方式打开文件。

O_ WRONLY:可写方式打开文件。

O_ RDWR:读写方式打开文件。

O_CREAT:如果该文件不存在,就创建一个新的文件, 并用第三的参数为其设置权限。

O_EXCL: 如果使用O_ CREAT时文件存在,则可返回错误消息。这一参数可测试文件是否存在

O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端。

O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据。

O_APPEND:以添加方式打开文件,所以对文件的写操作都在文件的末尾进行。

也可以选择多个参数,如我想实现如果只读一个文件,有就清空,无则新建,权限为0666:

O_ RDONLY|O_CREAT|O_TRUNC

整个函数为

fd = open("1.txt",O_ RDONLY|O_CREAT|O_TRUNC,0666);

文件的关闭:

int close(int fd);

fd为该文件的文件描述符。

成功返回0,出错返回EOF。

程序结束会自动关闭所以文件。

文件读取:

使用read函数:

ssize_t read(int fd,void *buf,size_t count);

和标准i/o按对象输入差不多,fd为文件描述符,第二个参数为缓冲区,用于存储读取的数据,第三个是要读取的数量。

成功会返回读取的实际个数,失败返回EOF。

都到末尾会返回0。

文件写入:

ssize_t write(int fd,void *buf,size_t count);

和read大致一致。

成功返回实际写入的数量,出错返回EOF。

文件的定位:

off_t lseek(int fd,off_t offset,intt whence);

成功返回当前文件读取的位置,参数与标准i/o一致。

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define N 64
int main(int argc,char *argv[]){
        int fds,fdt,n;
        char buf[N];
        if(argc < 3){
                printf("Usage : %s <sre_file> <dst_file>\n",argv[0]);
                return -1;
        }
        if((fds = open(argv[1],O_RDONLY)) == -1){
                fprintf(stderr,"open %s : %s\n",argv[1],strerror(errno));
                return -1;
        }
        if((fdt = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1){
                fprintf(stderr,"open %s : %s\n",argv[2],strerror(errno));
                return -1;
        }
        while((n = read(fds,buf,N)) > 0){
                write(fdt,buf,N);
        }
        close(fds);
        close(fdt);
        return 0;
}

库:

我们写程序的时候会用到头文件,也叫什么什么库,但是在编程过程中,如果想调用其他程序的函数,不一定要使用头文件的引用的方式,还有静态库和动态库。

静态库:

静态库是一个二进制文件,包含的代码可以被程序调用。

编译链接的时候,程序会把用得到的相关代码复制到可执行文件中,可执行程序就含有了此代码,后续运行使用都不再需要源文件,但是会占用更大的磁盘和内存。若静态库升级,还需要重新编译链接代码。

静态库程序和标准程序类似,但可以不存在int main函数,但是要有main函数。

在写完之后,原本是使用gcc -o test test.c生成可执行程序,改为 gcc -c test.c 生成二进制中间文件test.o。

再输入ar crs 静态库名称 .o文件 创建静态库,其中静态库名称由三部分组成1、lib,2、库名称,3、.a后缀,上述文件就是 ar crs libtest.a test.o。

编辑好主程序后,正在编译过程链接静态库:

gcc -o main main.c -L. -ltest

其中.c文件后面的 -L.为静态库路径,单个.表示当前目录,后续-l加库名称。

就可以实现链接啦。

动态库:

动态库是可执行文件在执行的时候才调用需要的代码模块的,多个程序可共享该库,但运行程序的时候需要源文件,否侧会报错,但升级方便,无需重新编译主程序。

动态库和静态库程序一样,但编译的时候不同:

gcc -c -fPLC test.c

才能生成动态库的二进制文件,然后建立共享库:

gcc -shared -o libcommon.so.1 test.0

其中-shared为关键字,libcommon.so.1为共享库名称,其中包括lib是固定格式,common为库名称,.so为共享库后缀,至于后面的.1是为方便管理版本什么的进行标记的。

然后还有创建关系链接:

ln -s libcommon.so.1 libcommon.so

这个就不可以有数字了

然后就是和主程序连接

gcc -o main mian.c -L. -lcommon

就可以啦。

库和头文件的对比:

特点 静态库 共享库 头文件库
文件大小 大(代码嵌入可执行文件) 小(代码在共享库中) 大(代码嵌入可执行文件)
编译方式 编译时链接 运行时链接 编译时包含
运行依赖 需要共享库文件
更新难度 难(需重新编译程序) 易(只需替换共享库文件) 易(需重新编译程序)
适用场景 小型项目、启动速度快 大型项目、更新频繁 小型库、模板库
相关推荐
Yeliang Wu2 分钟前
LLaMA-Factory 模型评估理论与实战:基于 Ubuntu 22.04 的系统化指南
linux·ubuntu·llama·评估·llamafactory
生信大表哥2 分钟前
单细胞测序分析(十一)轨迹分析
linux·rstudio·数信院生信服务器·生信云服务器
小糊涂加油5 分钟前
TypeScript学习笔记
笔记·学习
@游子7 分钟前
Python学习笔记-Day6
笔记·python·学习
躺着听Jay9 分钟前
【1267 - Illegal mix of collations 】mysql报错解决记录
java·linux·前端
xunyan623413 分钟前
面向对象(下)-模版方法的设计模式其应用场景
java·学习·设计模式
不秃头的帅哥15 分钟前
程序地址空间(基于c++和linxu的一些个人笔记
linux·开发语言·c++·操作系统·内存空间
Yweir16 分钟前
Linux性能监控的工具集和分析命令工具
java·linux·jvm
Tandy12356_17 分钟前
手写TCP/IP协议栈——无回报ARP包生成
c语言·c++·tcp/ip·计算机网络
XH-hui26 分钟前
【打靶日记】群内靶机Monkey
linux·网络安全