Linux——文件IO操作_linux系统实现文件io操作-程序员宅基地

技术标签: 运维  linux  服务器  

前言

        本篇文章主要是讲解在Linux环境下文件IO操作,包含文件IO中的基本概念以及一些常用的函数接口调用,希望可以给读者带来技术上的帮助!

一 、概念篇

Linux文件的种类:常规文件 -、目录文件 -d 、字符文件 -c 、块文件 -b 、链接文件 -l;

的概念:就是数据的流,在程序中就是一个结构体;

缓冲区的概念:为了减少操作IO设备的次数,调高运行效率,在内存里设置的缓冲区,分为全缓冲(缓冲区满才输出)和行缓冲(遇到换行符输出);

文件打开:占用资源;                                                                                      文件关闭:释放资源

文件IO:又称系统IO,系统调用,是操作系统提供的API接口函数。

二、标准IO

1.三种标准IO:

文件的打开函数:

FILE* fopen(const char* path, const char* mode);

path: 指打开文件的路径,普通文件按当前路径不需要加目录,其他要使用完整路径;

mode:文件的权限(0666);

返回值:出错返回NULL,所以使用fopen函数必须判断是否为空;

文件的打开模式:

文件的关闭函数:

int fclose(FILE* stream);

返回值:调用成功返回0,失败返回EOF(-1),并设置errno;

流关闭时自动刷新缓冲区中的数据并释放缓冲区,比如:常规文件把缓冲区内容写入磁盘;

当一个程序正常终止时,所有打开的流都会关闭;

形参文件流stream必须保证为非空,否则出现错误;

2.字符的输入(读单个字符)get

函数:

int fgetc(FILE* stream);        //流

int getc(FILE* stream);        //宏

int getchar(void);                 //键盘输入

返回值:成功时返回读取的字符,到文件末尾或出错时返回EOF(-1);

getchar()等同于 fgetc(stdin);

getc和fget区别是一个宏一个函数;

注意事项:

(1)函数返回值是int类型不是char类型,主要是为了扩展返回值的范围;

(2)stdin也是FILE*的指针,是系统定义好的,指向的是标准输入(键盘输入);

(3)打开文件按后读取,是从文件开头读,读完一个后读写指针会后移,读写注意指针的位置。

(4)调用getchar会阻塞,等待你的键盘输入;

3.字符的输出(写单个字符)put

函数:

int fputc(int c, FILE* stream);        //流

int putc(int c, FILE* stream);        //流

int putchar(int c);                          //屏幕

行输入(读取整行)get

函数:

char* gets(char *s);                //读取标准输入到缓冲区s,键盘

char* fgets(char *s, int size, FILE* stream);        //stream

返回值:成功时返回缓冲流s,到文件末尾会出错时返回NULL;

注意事项:

(1)gets函数已经被淘汰,因为会导致缓冲区溢出;

(2)fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区里,并且在最后面加'\0‘ ,如果输入数据少于size-1 后面会添加换行符;

行输出(写整行)

函数:

int puts(const char *s);

int fputs(const char* s, FILE* stream);

返回值:成功时返回非负整数,出错时返回EOF;

注意事项:

puts 将缓冲区s中的字符串输出到stdout,并追加'\n';

fputs 将缓冲区s中的字符串输出到stream,不追加’\n‘;

4.二进制读写

函数:

size_t fread(void *ptr, size_t size, size_t n, FILE *fp);

void *ptr  读取内容放的位置指针

 size_t size 读取的块大小

  size_t n 读取的个数

   FILE *fp  读取的文件指针

size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);

void *ptr  写文件的内容的位置指针

size_t size 写的块大小

size_t n 写的个数

  FILE *fp  要写的文件指针

注意事项:

文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容;

解决办法:移动指针到头文件(重定位);关闭文件,重新打开;

5.流的刷新        flash

int fflush(FILE* fp);

返回值:成功时返回0,出错时放回EOF;

将流缓冲区中的数据写入实际的文件;

Linux下只能刷新输出缓冲区,输入缓冲区丢弃;

如果输出到屏幕使用fflush(stdout);

6.流的定位        seek

函数:

long ftell(FILE* stream);

void rewind(FILE* stream);

long fseek(FILE* stream,long offset, int whence);

参数:

whence:SEEK_SET/SEEK_CUR/SEEK_END

SEEK_SET 从距文件开头 offset 位移量为新的读写位置

SEEK_CUR:以目前的读写位置往后增加 offset 个位移量

SEEK_END:将读写位置指向文件尾后再增加 offset 个位移量

offset:偏移量,可正可负

注意事项:

(1)文件的打开使用a模式fseek无效;

(2)rewind(fp)相当于fseek(fp,0,SEEK_SET);

(3)这三个函数只适用于2G以下的文件;

7.格式化输入输出

格式化输出:

int fprintf(FILE* stream,const char *fmt,...);

int sprintf(char* s,const char* fmt,.....);

返回值:成功时返回输出的字符个数;出错时返回EOF;

格式化输入:

int fscanf(FILE* stream,const char *format,...);

int sscanf(const char *str,const char* format,..);

重点掌握sprintf和sscanf;

三、文件IO

文件IO不提供缓冲机制

文件IO的API:open  close read read

文件描述符概念:

英文:缩写fd(file descriptor)

是0-1023的数字,表示文件。

0, 1, 2 的含义 标准输入,标准输出,错误。

1.文件IO打开和关闭

open

int open (const char* pathname,int flags);        //不创建文件

Int open(const char* pathname,int flags,mode_t mode);        //创建文件,不能创建设备文件成功时返回文件描述符;出错时返回EOF

文件IO和标准的模式对应关系:

r                                  O_RDONLY

r+                               O_RDWR

w                                O_WRONLY | O_CREAT | O_TRUNC, 0664

w+                              O_RDWR | O_CREAT | O_TRUNC, 0664

a                                 O_WRONLY | O_CREAT | O_APPEND, 0664

a+                               O_RDWR | O_CREAT | O_APPEND, 0664

close

int close(int fd);

关闭后文件描述符不能代表文件;

2.文件IO的读写及定位

read

函数:

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

返回值:成功时返回实际读取的字节数,出错时返回EOF;读到文件末尾是返回0;

参数:buf是接收数据的缓冲区;count不应超过buf大小;

write

函数:

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

返回值:成功时返回实际写入的字节数,出错时返回EOF;

参数:buf是接收数据的缓冲区;count不应超过buf大小;

lseek

函数:

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

返回值:成功时返回当前的文件读写位置;出错时返回EOF;

参数:offsethe whence同fseek完全一样;

四、目录操作

1.打开目录

函数:

DIR* opendir(const char* name);

DIR* fdopendir(int fd);                //使用文件描述符,要配合open函数使用

DIR是用来描述一个打开的目录文件的结构体类型,类似于FILE;

返回值:成功时返回目录流指针(DIR*);出错时返回NULL;

2.读取目录

函数:

struct dirent* readdir(DIR* dirp);

struct dirent是用来藐视目录流中一个目录项的结构体类型,包含成员char d_name[256]

返回值:成功时返回目录流dirp中下一个目录项;出错或末尾时返回NULL;

3.关闭目录

函数

 #include  <dirent.h>

 int closedir(DIR *dirp);

返回值:成功时返回0;出错时返回EOF

4.修改文件权限

函数:

 #include  <sys/stat.h>

 int  chmod(const char *path, mode_t mode);

 int  fchmod(int fd, mode_t mode);

成功时返回0;出错时返回EOF

注意:在vmwarewindows共享的文件夹下,有些权限不能改变。

5.获取文件属性

函数:

#include  <sys/stat.h>

 int  stat(const char *path, struct stat *buf);

 int  lstat(const char *path, struct stat *buf);

 int  fstat(int fd, struct stat *buf);

返回值:成功时返回0;出错时返回EOF

如果path是符号链接stat获取的是目标文件的属性;而lstat获取的是链接文件的属性

五、库的调用

1.静态库

创建步骤:

(1)编写库文件代码,编译为.o 目标文件。

(2)ar 命令 创建  libxxxx.a 文件

   ar -rsv  libxxxx.a  xxxx.o

   注意:  静态库名字要以lib开头,后缀名为.a

                没有main函数的.c 文件不能生成可执行文件。

链接错误:

test.c:(.text+0x15):对‘hello’未定义的引用

collect2: error: ld returned 1 exit status

含义:表示hello函数在编译的源码内没有找到实现

解决:实现代码或者找到对应函数的库并且链接它。

链接静态库:

gcc -o 目标文件 源码.c  -L路径  -lxxxx

-L  表示库所在的路径

-l 后面跟库的名称

2.动态库

创建步骤:

(1)生成位置无关代码的目标文件

 gcc  -c  -fPIC  xxx.c xxxx.c ....

(2)生成动态库

   gcc  -shared -o libxxxx.so  xxx.o  xxx.o ....

(3)编译可执行文件

gcc -o 目标文件 源码.c  -L路径  -lxxxx

可执行文件错误:

./test: error while loading shared libraries: libmyheby.so: cannot open shared object file: No such file or directory

含义:可执行文件所使用的动态库找不到

解决办法:

找到动态库,添加到/usr/lib里面

或者使用export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库目录

添加在~/.bashrc 文件里面,使用source ~/.bashrc 生效。

六、个人总结

        本文讲解了三种类型IO操作以及库,三种类型分别是标准IO、文件IO以及目录,三者既有不同点又有相同点。三种都有打开、读写及关闭,对于标准IO来说,每个函数前以字母f打头(fopen\fclose\fseek等),文件IO则是直接open、close,目录得在后面加上dir来区别,并且标准IO有结构体类型的文本流FILE,文件IO有int类型的文本描述符f,目录则是由结构体类型的目录流DIR。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_52706451/article/details/136949377

智能推荐

FTP命令字和返回码_ftp 登录返回230-程序员宅基地

文章浏览阅读3.5k次,点赞2次,收藏13次。为了从FTP服务器下载文件,需要要实现一个简单的FTP客户端。FTP(文件传输协议) 是 TCP/IP 协议组中的应用层协议。FTP协议使用字符串格式命令字,每条命令都是一行字符串,以“\r\n”结尾。客户端发送格式是:命令+空格+参数+"\r\n"的格式服务器返回格式是以:状态码+空格+提示字符串+"\r\n"的格式,代码只要解析状态码就可以了。读写文件需要登陆服务器,特殊用..._ftp 登录返回230

centos7安装rabbitmq3.6.5_centos7 安装rabbitmq3.6.5-程序员宅基地

文章浏览阅读648次。前提:systemctl stop firewalld 关闭防火墙关闭selinux查看getenforce临时关闭setenforce 0永久关闭sed-i'/SELINUX/s/enforcing/disabled/'/etc/selinux/configselinux的三种模式enforcing:强制模式,SELinux 运作中,且已经正确的开始限制..._centos7 安装rabbitmq3.6.5

idea导入android工程,idea怎样导入Android studio 项目?-程序员宅基地

文章浏览阅读5.8k次。满意答案s55f2avsx2017.09.05采纳率:46%等级:12已帮助:5646人新版Android Studio/IntelliJ IDEA可以直接导入eclipse项目,不再推荐使用eclipse导出gradle的方式2启动Android Studio/IntelliJ IDEA,选择 import project3选择eclipse 项目4选择 create project f..._android studio 项目导入idea 看不懂安卓项目

浅谈AI大模型技术:概念、发展和应用_ai大模型应用开发-程序员宅基地

文章浏览阅读860次,点赞2次,收藏6次。AI大模型技术已经在自然语言处理、计算机视觉、多模态交互等领域取得了显著的进展和成果,同时也引发了一系列新的挑战和问题,如数据质量、计算效率、知识可解释性、安全可靠性等。城市运维涉及到多个方面,如交通管理、环境监测、公共安全、社会治理等,它们需要处理和分析大量的多模态数据,如图像、视频、语音、文本等,并根据不同的场景和需求,提供合适的决策和响应。知识搜索有多种形式,如语义搜索、对话搜索、图像搜索、视频搜索等,它们可以根据用户的输入和意图,从海量的数据源中检索出最相关的信息,并以友好的方式呈现给用户。_ai大模型应用开发

非常详细的阻抗测试基础知识_阻抗实部和虚部-程序员宅基地

文章浏览阅读8.2k次,点赞12次,收藏121次。为什么要测量阻抗呢?阻抗能代表什么?阻抗测量的注意事项... ...很多人可能会带着一系列的问题来阅读本文。不管是数字电路工程师还是射频工程师,都在关注各类器件的阻抗,本文非常值得一读。全文13000多字,认真读完大概需要2小时。一、阻抗测试基本概念阻抗定义:阻抗是元器件或电路对周期的交流信号的总的反作用。AC 交流测试信号 (幅度和频率)。包括实部和虚部。​图1 阻抗的定义阻抗是评测电路、元件以及制作元件材料的重要参数。那么什么是阻抗呢?让我们先来看一下阻抗的定义。首先阻抗是一个矢量。通常,阻抗是_阻抗实部和虚部

小学生python游戏编程arcade----基本知识1_arcade语言 like-程序员宅基地

文章浏览阅读955次。前面章节分享试用了pyzero,pygame但随着想增加更丰富的游戏内容,好多还要进行自己编写类,从今天开始解绍一个新的python游戏库arcade模块。通过此次的《连连看》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。_arcade语言 like

随便推点

【增强版短视频去水印源码】去水印微信小程序+去水印软件源码_去水印机要增强版-程序员宅基地

文章浏览阅读1.1k次。源码简介与安装说明:2021增强版短视频去水印源码 去水印微信小程序源码网站 去水印软件源码安装环境(需要材料):备案域名–服务器安装宝塔-安装 Nginx 或者 Apachephp5.6 以上-安装 sg11 插件小程序已自带解析接口,支持全网主流短视频平台,搭建好了就能用注:接口是公益的,那么多人用解析慢是肯定的,前段和后端源码已经打包,上传服务器之后在配置文件修改数据库密码。然后输入自己的域名,进入后台,创建小程序,输入自己的小程序配置即可安装说明:上传源码,修改data/_去水印机要增强版

verilog进阶语法-触发器原语_fdre #(.init(1'b0) // initial value of register (1-程序员宅基地

文章浏览阅读557次。1. 触发器是FPGA存储数据的基本单元2. 触发器作为时序逻辑的基本元件,官方提供了丰富的配置方式,以适应各种可能的应用场景。_fdre #(.init(1'b0) // initial value of register (1'b0 or 1'b1) ) fdce_osc (

嵌入式面试/笔试C相关总结_嵌入式面试笔试c语言知识点-程序员宅基地

文章浏览阅读560次。本该是不同编译器结果不同,但是尝试了g++ msvc都是先计算c,再计算b,最后得到a+b+c是经过赋值以后的b和c参与计算而不是6。由上表可知,将q复制到p数组可以表示为:*p++=*q++,*优先级高,先取到对应q数组的值,然后两个++都是在后面,该行运算完后执行++。在电脑端编译完后会分为text data bss三种,其中text为可执行程序,data为初始化过的ro+rw变量,bss为未初始化或初始化为0变量。_嵌入式面试笔试c语言知识点

57 Things I've Learned Founding 3 Tech Companies_mature-程序员宅基地

文章浏览阅读2.3k次。57 Things I've Learned Founding 3 Tech CompaniesJason Goldberg, Betashop | Oct. 29, 2010, 1:29 PMI’ve been founding andhelping run techn_mature

一个脚本搞定文件合并去重,大数据处理,可以合并几个G以上的文件_python 超大文本合并-程序员宅基地

文章浏览阅读1.9k次。问题:先讲下需求,有若干个文本文件(txt或者csv文件等),每行代表一条数据,现在希望能合并成 1 个文本文件,且需要去除重复行。分析:一向奉行简单原则,如无必要,绝不复杂。如果数据量不大,那么如下两条命令就可以搞定合并:cat a.txt >> new.txtcat b.txt >> new.txt……去重:cat new...._python 超大文本合并

支付宝小程序iOS端过渡页DFLoadingPageRootController分析_类似支付宝页面过度加载页-程序员宅基地

文章浏览阅读489次。这个过渡页是第一次打开小程序展示的,点击某个小程序前把手机的开发者->network link conditioner->enable & very bad network 就会在停在此页。比如《支付宝运动》这个小程序先看这个类的.h可以看到它继承于DTViewController点击左上角返回的方法- (void)back;#import "DTViewController.h"#import "APBaseLoadingV..._类似支付宝页面过度加载页

推荐文章

热门文章

相关标签