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

就可以啦。

库和头文件的对比:

特点 静态库 共享库 头文件库
文件大小 大(代码嵌入可执行文件) 小(代码在共享库中) 大(代码嵌入可执行文件)
编译方式 编译时链接 运行时链接 编译时包含
运行依赖 需要共享库文件
更新难度 难(需重新编译程序) 易(只需替换共享库文件) 易(需重新编译程序)
适用场景 小型项目、启动速度快 大型项目、更新频繁 小型库、模板库
相关推荐
简鹿办公2 小时前
重大更新!Ubuntu Pro 现提供长达 15 年的安全支持
linux·安全·ubuntu
01100001乄夵2 小时前
FPGA模块架构设计完全入门指南
经验分享·笔记·学习方法·fpga入门·fpga学习之路
01100001乄夵2 小时前
FPGA零基础入门:Verilog语法攻略
经验分享·笔记·学习方法·fpga入门·fpga学习之路
Nuyoah11klay2 小时前
华清远见25072班单片机高级学习day1
单片机·嵌入式硬件·学习
qq_321665332 小时前
验证centos 服务器(或其他linux服务器),443或80端口是否开通
linux·服务器·centos
java_logo2 小时前
TOMCAT Docker 容器化部署指南
java·linux·运维·docker·容器·tomcat
受之以蒙2 小时前
Rust ndarray 高性能计算:从元素操作到矩阵运算的优化实践
人工智能·笔记·rust
whb2341741242 小时前
测试linux删除Oracle文件,使用文件句柄恢复
linux·运维·oracle
霜绛2 小时前
Unity:lua热更新(一)——AB包AssetBundle、Lua语法
笔记·学习·游戏·unity·lua