文件IO——文件IO的API

以下内容源于网络资源的学习与整理,如有侵权,请告知删除。

文件操作的一般步骤

在Linux系统中要操作一个文件,一般是先使用open函数打开文件,得到一个文件描述符,然后对文件进行读写操作(或其他操作),最后close关闭文件即可。

为何打开一个大文件时比较慢?

文件平时存放在块设备中的文件系统中,我们把这种文件叫静态文件。当使用open函数打开一个文件时,内核在进程中建立一个数据结构,记录我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内存中特定地址管理存放(叫动态文件)。

为什么我们写了一半的文件,如果没有点保存直接关机/断电,重启后文件内容丢失。

打开文件后,对文件的读写操作,都是针对内存中这一份动态文件的,而并不是针对静态文件的。当我们对动态文件进行读写后,内存中的动态文件与块设备中的静态文件就不同步了。当我们使用close函数关闭动态文件时,内核会将将内存中的动态文件更新到块设备中的静态文件中。

因为块设备本身有读写限制,而内存可以按字节为单位来操作,而且可以随机操作,所以这样设计。

Llinux常用文件IO的API

常见的文件IO的API包括:open、close、write、read、lseek。

这些API的用法可以在命令行输入“man 2 xxx”进行了解。

一、open函数

函数原型

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

函数作用

open打开一个文件,返回该文件的文件描述符。

参数说明

(1)pathname表示文件的路径。

(2)flags表示一些读写权限。

特别说明

关于open函数中flags的含义,见博文文件IO4——open函数的参数flags详解_天糊土的博客-CSDN博客

代码示例

无。

二、close函数

函数原型

int close(int fd);

函数作用

close函数关闭一个文件。成功则返回0,失败则返回-1。

参数说明

fd 是要关闭的文件的文件描述符。

特别说明

无。

代码示例

无。

三、write函数

函数原型

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

函数作用

write函数将内存缓冲区buf中的count个字节数据写入fd所表示的文件中。

参数说明

(1)fd表示要写入哪个文件,fd一般由前面的open返回得到。

(2)buf是应用程序自己提供的一段内存缓冲区,用来存储要写入的内容。

(3)count是我们要写入的字节数。

(4)ssize_t类型是linux内核用typedef重定义的一个类型(其实就是int)。

特别说明

见read函数中的特别说明。

代码示例

无。

四、read函数

函数原型

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

函数作用

从fd所表示的文件中读取count个字节到buf中。返回值表示成功读取的字节数。

参数说明

(1)fd表示要读取哪个文件,fd一般由前面的open返回得到。

(2)buf是应用程序自己提供的一段内存缓冲区,用来存储读出的内容。

(3)count是我们要读取的字节数。

(4)ssize_t类型是linux内核用typedef重定义的一个类型(其实就是int)。

特别说明

(1)count和返回值的关系

count参数表示想要写或者读的字节数,返回值表示实际完成的写的或者读的字节数。实现的有可能等于想要写的,也有可能小于(说明没完成任务)。

(2)阻塞的情况

如果一个函数是阻塞式的,我们要读30个,结果读20个时就被阻塞住,等待剩余的10个可以读。

(3)count取值多少适宜

我们写程序时,如果要读取或者写入的是一个很庞大的文件(譬如文件有2MB),不能把count设置为2*1024*1024,而应该把count设置为一个合适的数字(譬如2048、4096),然后通过多次读取来实现全部读完。

代码示例

无。

五、lseek函数

函数原型

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

函数作用

将文件描述符fd所表示的文件的文件指针,以whence为参照基准,往后移动offset个字节。返回值表示实际偏移的字节数。

参数说明

(1)fd表示文件的描述符。

(2)offset表示偏移量(以字节为单位)。

(3)whence表示参照基准,比如SEEK_END\SEEK_SET\SEEK_CUR,分别表示文件尾、文件头、当前位置。

特别说明

lseek函数介绍
文件流很长,如何得知目前正在操作的位置?GUI模式下的软件用光标来标识当前正在操作的位置。在动态文件中,使用文件指针来表征这个正在操作的位置。这个指针不能被直接访问,Linux系统用lseek函数来访问这个文件指针

打开一个空文件时,默认情况下文件指针指向文件流的开始,如果这时候去write,则是从文件开头处开始写入的。write和read函数本身自带移动文件指针的功能,所以write了n个字节后,文件指针也会自动向后移动n位。如果需要人为地随意地更改文件指针,只能通过lseek函数。

因为read和write函数都是从文件指针处开始操作的,所以使用lseek函数将文件指针移动后,read/write时就是从移动过后的文件指针所指的位置开始的。

lseek的应用情景

(1)用lseek计算文件长度

Linux中并没有一个函数可以直接返回一个文件的长度,但是我们做项目时经常需要知道一个文件的长度,这时候可以利用lseek来写一个函数得到文件长度。

代码实现

ret=lseek(fd,0,SEEK_END);

(2)用lseek构建空洞文件

空洞文件就是这个文件中有一段是空的(不是非可视字符,而是真的没有内容,但是占据存储空间)。普通文件中间是不能有空的,因为我们write时文件指针是依次从前到后去移动的,不可能绕过前面直接到后面。我们打开一个文件后,用lseek往后跳过一段,再write写入一段,就会构成一个空洞文件。

空洞文件方法对多线程共同操作文件是极其有用的。有时候我们要创建一个很大的文件,如果从头开始依次构建的话,耗费的时间很长。我们可以将文件分为多段,然后利用多线程,每个线程负责其中一段的写入。

代码示例

无。

六、exit、_exit、_Exit 函数

当程序在前面步骤失败导致后面的操作不能继续进行时,应该在前面的错误监测中结束整个程序。

结束程序有两种方法:

第一种:在main用return,一般原则是程序正常终止return 0,如果程序异常终止则return -1。
第二种:使用exit、_exit、_Exit三者之一。

七、perror函数

errno

Linux系统中对各种常见错误做了编号,当函数执行错误时,函数会返回一个特定的errno编号来告诉我们这个函数到底哪里错了。

errno全称是error number,意思是“错误号码”。它是由OS来维护的一个全局变量,任何OS内部函数都可以通过设置errno来告诉上层调用者究竟刚才发生了一个什么错误。

errno本质是一个int类型的数字,每个数字编号对应一种错误。我们从errno这个变量里只能得知它的值是多少,不知道这个值所代表的错误信息。

perror函数

因此Linux系统提供了一个perror函数(意思print error)(它用命令man 2 xxx显示不出来,要用man 3 xxx才行。这说明它是C库函数?)。perror函数内部会读取errno,然后将这个不好认的数字转换成对应的错误信息字符串,然后print打印出来。

八、dup函数 

dup函数原型

int dup(int oldfd);

dup函数作用

该函数对旧的fd进行复制,返回值是一个新的文件描述符。

参数说明

oldfd是要进行复制的文件描述符。

补充说明

(1)dup函数不能指定复制得到的fd的值,而是由操作系统内部自动分配的。分配的原则遵守fd分配的原则,即分配没被占用的且数值最小的fd。

(2)dup函数返回的fd,和原来的oldfd,都表示原来oldfd所表示的那个动态文件,操作这两个fd实际操作的是oldfd表示的那个文件。这就构成了文件共享。(文件共享的三种方式之一,其他两种方式:同一进程中多次使用open函数打开同一文件,不同进程中打开同一文件。)

(3)利用dup返回的fd和原来的oldfd同时向一个文件写入时,结果应该是分别写。

(4)标准输出的重定位

利用上面3点的补充说明,可以实现标准输出的重定位。我们已知fd=0,1,2默认分别被标准输入文件、标准输出文件、错误通道文件占用,但我们可以使用close函数关闭这三个文件。比如我们可以用close(1)来关闭标准输出,关闭后我们使用printf函数时,屏幕上不再显示内容输出的内容。close(1)之后,fd=1这个就空出来了,没有被占用。由于dup函数分配fd时,分配没被占用且数值最小的fd,那么我们使用dup函数去复制文件 test.txt 的fd时,返回的fd就是之前被释放不在被占用的fd=1。这样一来,fd=1就指向了文件test.txt。由于fd=1所表示的文件被默认是标准输出,所以使用echo命令、ls命令、printf函数等,都会将显示的内容输出到文件test.txt里面。这就实现了标准输出的重定位。

也就说,可以利用“open文本文件得到文件描述符+close标准输出的文件描述符+dup文本文件的描述符”的形式,实现标准输出的重定位。

Linux 中的重定位符“>”,其实也是利用open+close+dup来实现的。open打开一个文件2.txt,然后close关闭stdout,然后dup将1和2.txt文件关联起来即可。

九、fcntl函数

函数原型

int fcntl(int fd, int cmd, ... /* arg */ );

函数作用

fcntl函数是一个多功能的文件管理的工具箱。

参数说明

(1)fd表示此函数要操作的文件的文件描述符。

(2)cmd表示此函数要进行的操作。

(3)变参用来传递参数,配合cmd使用。

补充说明

(1)cmd的样子类似于F_XXX,不同的cmd具有不同的功能。

(2)fcntl函数常用的cmd:F_DUPFD

此cmd的作用是复制文件描述符,类似于dup函数。

它从可用的fd数字列表中找一个大于或者等于arg的数字作为原来文件描述符的复制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】功能测试的经验总结

测试准备: 1、实际测试总比你预想的要花更多的时间,遇到更多的麻烦,所以要尽量争取足够的测试时间,不要不加思索的说这个东西我一星期肯定可以测完。还要尽可能考虑到测试过程中的风险,比如测试环境的问题、部署失败的…

文件IO——open函数的参数flags详解

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 前言 在命令行中使用“man 2 open”可以获知open这个文件IO API的使用方法。 open函数的模型有两种,根据需要选择其中一种即可。 int open(const char *pathname, int flags); int open(…

oracle建库及plsql建表空间的用法

所有程序—》ORACLE-JHEMR-----------》配置和移植工具-----》DataBase Configuration Assistant-------中间就需要改一个数据仓库即可,其他的都是下一步,统一口令为**然后建监听服务,测试时改登录为system **,之后用plsql登录上&…

USACO 1.5.4 Checker Challenge

题意:经典的八皇后问题 解法: 采用朴素的每一次放置都与前面的所有行进行比较,在N 13的时候时间会爆掉 《入门经典》上提供的方法很经典,vis数组的使用,具体见《入门经典》125页 /* ID:lsswxr1 PROG:checker LANG:C */…

Spark 1.1.1 Submitting Applications

回到目录 Submitting Applications The spark-submit script in Spark’s bin directory is used to launch applications on a cluster. It can use all of Spark’s supported cluster managersthrough a uniform interface so you don’t have to configure your applicatio…

如何描述变量:存储类、生命周期,作用域、链接属性

可以根据一个变量的存储类、作用域、链接属性、生命周期来描述该变量。 其中,存储类决定了生命周期,作用域决定了链接属性。 存储类 存储类表明变量在哪里存储。见博文Linux下C语言程序的内存布局_天糊土的博客-CSDN博客 作用域 作用域表明变量起作用的…

mysql 修改表名的方法:sql语句

在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢? 可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦。 能否简…

java String类 常用函数

为什么80%的码农都做不了架构师?>>> 1. 获取 int indexOf(int c) int indexOf(int c, int start) char charAt(int index) 2.判断 判断是否包含一个字符串 boolean contains(CharSequence cs) indexOf() //也可以用来判断是否包含 判断是否有内容 boole…

设备驱动程序的简介

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、驱动的概念 设备驱动程序(Device Driver),简称驱动程序、驱动(Driver),指操作系统中用来操控硬件的代码。 驱动是硬件与操…

Android开发实践:掌握Camera的预览方向和拍照方向

Android的Camera相关应用开发中,有一个必须搞清楚的知识点,就是Camera的预览方向和拍照方向,本文就重点讨论一下这个问题。图像的Sensor方向:手机Camera的图像数据都是来自于摄像头硬件的图像传感器(Image Sensor&…

mknod命令:创建设备文件

参考博客:mknod_liangkaiming的博客-CSDN博客 参考资料:man手册 可以通过man 1 mknod查看mknod命令的内容。 1、mknod 命令的作用是make block or character special files,即创建块设备或者字符设备文件。 2、mknod 命令的格式是&#xf…

DreamWeaver使用技巧学习心得

全是我在平时学习网页时积累的,觉得会对遇到同样问题的友人有帮助,都是一些觉得困惑好久然后豁然开朗的心得。 希望大家都能体会到,解决难题后的快乐。 都是我恍然大悟的地方,不够恍然大悟的就不贴上来了。 1.让一个区块居中&…

【转】每天一个linux命令(39):grep 命令

原文网址:http://www.cnblogs.com/peida/archive/2012/12/17/2821195.html Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全…

SecureCRT显示乱码的解决办法

发现问题 在Ubuntu中编写代码,输出语句里带有中文,比如"printf("读出来的内容是:%s.\n", buf);"。使用交叉编译工具链编译后,将可执行程序转移至开发板系统运行,并使用SCRT来观测测试结果。此时发…

WCF数据契约

当使用DataMember时,和访问符无关,及时使用了private,成员都是可见的。相反如果使用static,为不可见。 上述的两个数据成员是等效的,如果是等效的话 数据成员的顺序也必须是相同的。 4.数据契约已知类型——使用KownTy…

Linux中NFS服务器的配置(/etc/export)

本文转载于NFS /etc/exports参数解释,有修改。 问题引入 之前利用NFS从ubuntu中下载根文件系统到开发板(见博客以NFS方式挂载rootfs的设置方法),但只是遵照教程安装的,对里面的设置含义不是很清楚。后来在开发板上上进…

cocos2d 很水很水的看法

这几天接了个扯淡的项目 cocos2d的 。 本来以为是Cpp的, 结果不是2dx ,而是OC的2d。看了几天的官方的dome ,大概知道是什么样子的。我就简单的纪录一下好了: cocos2d的整个框架呢, 分为3层 — 类似舞台剧 演戏嘛 肯定有个boss的 …

详解EBS接口开发之采购申请导入

更多内容可以参考我的博客 详解EBS接口开发之采购订单导入 http://blog.csdn.net/cai_xingyun/article/details/17114697 /*--将数据写入至采购申请接口表*/PROCEDURE insert_procure_main(errbuf OUT NOCOPY VARCHAR2,retcode OUT NOCOPY VARCHAR2)…

sys文件系统

以下内容源于网络资源的学习与整理,如有侵权请告知删除。 前言 Linux2.6版本的内核引入了sys文件系统。 在 proc文件系统介绍和使用 中,介绍了sys文件系统与proc文件系统的差异。它们都是虚拟文件系统,都是内核中的数据结构的可视化接口。它…

spring mvc 配置解析之xml

2019独角兽企业重金招聘Python工程师标准>>> ##mvc.xml中可配置的元素## 既然是xml,当然是要遵循schema的规定. 那么schema文件在哪呢? 定位方法就是解开这个jar文件,找到META-INF/spring.schema文件,这是个文本文件,里面包含了namespace以及其对应的xsd文件的位置…