linux下的文件操作

linux下的文件操作

概述

       linux系统将一切都视为文件,文件操作十分重要,有在win系统下使用过C语言的人知道,c语言常用的文件操作函数有fopen,fclose,fwrite,fread,ffluse等等,而在linux系统下,文件操作应该分为两类,一类是系统调用,一类是库函数,也就是刚刚所列举的函数,对于初学c语言,接触到文件,很多描述即使在入门书上讲的也难懂,所以这里以自己的理解来梳理一下linux下的文件操作函数

系统调用

       首先对于文件我们的操作操作思路无非是打开文件,读文件,写文件,关闭文件等等,下面就按照这样的思路进行数列


系统调用函数原型有

1.open函数
open函数有两个函数原型,如下所示:
int open(const char *path,int oflag);
int open(const char *path,int oflag,mode_t mode);

       首先有这么一个问题,假如对于一个人来说,打开文件我们需要知道什么,也就是说,我们要告诉计算机什么

       不用多想,肯定是得知道文件的位置和名称啊,不然,操作系统为我们打开哪一个文件对不对,明白了这一点,那么函数原型的第一个参数就知道是什么意思了,const char *path就是来指定函数要打开文件的路径的。注意参数类型是const char*,也就是我们要传递的应该是一串记录文件路径和名称的字符串。

       既然要打开一个文件,打开文件的目的是什么,读和写呗,但是到底要读还是要写呢,也就是说我们得告诉操作系统我们要怎么操作文件,你给我按照这种方式打开,这就是int oflag的作用,初看这个参数,说要传入一个整数给函数,但是我怎么知道哪个整数对应哪种打开方式,不要害怕,我也不知道,因为函数库已经用宏定义给我们定义好了,我们只要记住有哪一些就行了,甚至不记住也可以,用的时候再查就可以了,那么我们来列举一下吧

1.O_RDONLY
       见名知意,这不就是read only吗,也就是说以只读的方式打开,好,什么是只读呢,只读就是说我只可以读,打一个比方,给你一张纸,纸上有字,你只可以看,但是,你却不能写,这就是只读模式。
2.O_WRONLY
       见名只意,这就是只写,什么意思呢,给你一张纸,上面有字,但是呢,你得把眼睛闭上,眼睛闭上了就不看到纸上的内容了,这时候我问你,上面写了什么,你当然是不知道的,但是呢,你有手啊,你可以在上面写写画画对不对。
3.O_REWR
       这个根据前面的可以知道,可读可写模式,终于可以正常的读纸上的内容了,这时候不光可以看还可以写。
当然了强大的linux系统不仅仅给我们提供这些模式,继续
4.O_APPEND
       单词append的意思就是增补的意思,顾名思义,想想看,当我打开一个文件,下一步要进行写操作,那么我该怎么写呢,其实可以想到的方式有很多,其中有一种便是接着文件内容后面继续写。这就是该模式的解释
5.O_TRUNC
       单词truncate的意思是删节的意思,书上讲这个命令的时候,也是讲的删节,但是什么是删节嘛,这个自己猜想是把文件内容打开,然后情空,后来做了实验,发现的确如此,各位读者也可以自行实验,也许我说的不是对的。
6.O_CREAT
       这个单词好理解,就是creat创建的意思嘛,为什么会有这个模式的,假设我第一个参数传入,程序去寻找我指定的文件,由于某些不可抗拒的原因,文件竟然不存在,那么你说咋办,程序咋办,总得打开一个呀,那么只能自己创建一个空的文件然后打开了,所以该模式是如果文件不存在则创建。
7.O_EXCL
       有没有这样一种可能,在多线程环境下,两个运行的程序打开了同一个文件,然后进行操作,这样一来就可能乱套了,为了防止这种情况的发生,就有了这个模式,该模式是防止一个文件被多个程序打开。

       好了,常用的模式就这些了,但是,当我不满足与其中一个模式怎么办,比如说我想先清除内容然后以只写的模式打开,这个时候势必就要用两个模式了,这样可以么,那么参数不就便多了么?当然可以了,linux很强大的,我们可以通过或运算符“|”将多个不同的模式组合起来达到使用多个模式的目的。

       下面来讲第三个参数,问大家一个问题,为啥要有两个函数原型呢,第一个难道不能满足我们的需求吗,给点提示,大家想一下O_CREAT模式
       聪明的人可能已经发现可,在linux下,文件都有自己的文件权限,你可以用ls -l查看一下,当我们打开一个已经存在的文件,自然他的文件访问权限已经有了,可是不存在该文件,我们又希望程序创建一个文件,那么该文件的文件访问权限是否可以设置呢,这也就是第三个参数的作用了,常用的模式也是以宏定义的形式给出。
1.S_IRUSR
2.S_IWUSR
3.S_IXUSR
       我们讲这看成一组,因为这是对于文件所有者的,R,W,X分别对应于可读可写可执行,如果讲USR换成GRP或者OTH则对于的是文件所属组和其他人的权限。
当然我们也可以用或运算符讲不同的属性组合起来。

       所有的参数都讲完了,接下来就是返回值了,返回值的类型是int型,那么这有什么含义呢,大家都知道,打开一个文件是为了为后面的读写操作做准备,换句话说,我现在用open打开了一个文件,接下来我要写文件读文件,我如何知道我打开的文件是什么呢?
       在linux操作系统中,有一种神奇的东西叫做文件描述符,他也是一个整数来表示的,用来确定某个打开的文件的,通常这由操作系统来分配,我们的open函数返回的就是这么一个东西,如果打开文件成功则返回一个文件描述符,否则返回-1,并设置全局变了erren来说明错误的原因。再换一句话说,我们要打开一个文件,实际上就是要得到这个文件的描述符,然后再做下一步操作。
open函数就讲到这里了。

到了这里相信大家会打开文件了,那么现在就要来操作文件了。
read函数
read函数从文件中读取指定字符数量的内容并放入缓冲区。
size_t read(int fildes,void *buf,size_t nbytes);
       按照老规矩,先来剖析一下参数,我们要读一个文件,首先要做的就是知道我要读哪一个文件,fildes猜一下是什么,看参数类型,竟然是int型的,有没有想法呢,我们之前说了,linux操作系统用文件描述符来标记被打开的文件,所以这里传的就是你要打开的那个文件的文件描述符,不要再问我文件描述符怎么获取,当然用open啦,有一点值得注意,程序运行是有三个文件被默认的打开,他们分别是stdin,stdout,stderr,他们的文件描述符分别为0,1,2。至于他们是什么,自己百度吧。
       知道读哪个文件了,那么下面的问题就是我要读的东西放哪里,看概述就知道,放缓冲区啊,但是作为一个初学者,神tm知道缓冲区是什么过,这里也不做解释 ,只是说这是一个可以存放数据的地方,比如说自定义的数组之类的了,一般我们都是用自定义的字符串数组做参数的,知道了要读哪个文件,也知道了要把独到的东西记录到哪里,最后最后一个问题是,我到底要读多少啊,这也就是第三个参数的作用,指定读取的字符的数量。
好了现在来看返回值吧,返回值是size_t,表示读取成功的字符数量,我们可以通过返回值和第三个参数是否相等来判断是否读取成功。那么还要一个问题什么时候算失败呢,第一读取到文件尾了,第二缓冲区太小了装不下要读入的字符,第三,程序脑抽了,当然这种情况太小了。
write函数
size_t write(int fildes,const void *buf,size_t nbytes);
       看到函数原型有没有和read函数很像,就是,他们就是一对的,那么我就不用多解释什么了,这个函数是把指定数量的内容冲缓冲区写进文件。
close函数
int close(int filedes)传入文件描述符号
       人要有始有终打开了就要关上才能避免不必要的麻烦出现,这个函数就是用来关闭文件的,但是有人回文联,出现结束后,文件自己就关闭了,为什么还要手动来关闭呢,一方面,我们是为了防止发生意外,另一方面,既然一个程序不对这个文件进行操作了,不关闭它,别的程序不就不方便对这个文件进行操作么。另外一个程序打开的文件的数量是有限的,万一后面还要打开很多文件咋办呢,这种占着茅坑不拉屎的行为我们不能干,所以在程序中我们还是手动的关闭不需要使用的文件吧。
       系统调用函数就写到这里了当然肯定没有讲完,但作为初学者已经足够了,下面来讲库函数中的文件操作吧。
       linux的系统调用只是针对linux系统,如果用了上面的函数,然后在win系统下运行肯定会有问题的,而库函数就没有这个局限性了,库函数完全可以实现上面的功能,并且和操作系统无关。下面是介绍几个库函数

库函数

fopen
打开一个文件
FILE * fopen(const char * path,const char * mode);
       注意这里的返回值,这个时候文件用文件指针来表示,函数打开一个文件后会返回指向该文件的指针,获得了这个指针后续的操作才能够得以进行。

第一个参数:文件路径名
第二个参数:打开方式
关于打开模式就比之前的系统调用简单多了

w 以只写方式打开文件,文件原有的内容会被清空掉,如果文件不存在则建立这个文件
w+以读写方式打开文件,文件内容会被清空
r 以只读方式打开文件,文件必须存在
r+以读写方式打开文件,文件必须存在
a 以附加的方式打开文件,内容会附加在文件末尾,如果文件不存在则创建文件,原来的EOF保留
a+以附加的方式打开文件,内容会附加在文件末尾,如果文件不存在则创建文件,原来的EOF不保留
什么是EOF呢?
EOF是end of file的缩写,表示文件结束符

fclose
关闭一个文件,这个比较简单
int fclose(FILE *fp);
参数为指向要关闭的文件的文件指针,关闭成功返回0,否则返回EOF(-1).

fread
在文件中读取内容
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
第一个参数是缓冲区
第二个参数是每次要读取的数量
第三个参数是要读的次数
第四个参数要读取的文件的文件指针
返回值是成功读取到的字符数量
有了对read的了解,这些应该都不难理解,这里就不做详细解释

fwrite
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
第一个参数:要写的内容
第二个参数:要写入的数量
第三个参数:要写入的次数
第四个参数:目标文件指针
返回值:实际写入的数据项

fflush
int fflush(FILE *stream);
       在文件读写时,并不是一次到位的,操作系统总是把内容先放入缓冲区,这样存在的问题就是,如果文件被异常关闭,但是此时缓冲区还有内容怎么办,这时候就应该调用该函数,强制把缓冲区的内容写入。其实fclose调用时也自动调用了一次该函数。

fseek
       通过上面的介绍有没有发现,文件操作并不是很灵活,首先我们似乎只能在文件开头很文件尾进行操作,这样明显现在了我们的很多行为,这个函数就是来移动文件指针指向的位置的,来控制写入或者读取的位置在哪里。int fseek(FILE stream, long offset, int fromwhere);
我会详细介绍这个函数的用法,这里只做了解性的认识。


       这是一篇很长的博客,将近5000字了,写作的目的是为了帮助自己更好的理解,也是将自己的想法分享给其他人,当然我并不能保证自己所写的内容是否表达恰当,欢迎各位读者指教
来自长沙理工大学的2017级大一新生一名,你可以联系我:807920489(qq)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值