基础IO之文件操作

目录

一 C语言层面的文件操作

1 打开文件 fopen

 2 fclose 关闭文件

3 fwrite fprintf fputs

①fwrite ​编辑

②fprintf

③fputs

4 fgets

模拟实现mycat

二 系统接口的使用

1open

①如何给函数传递标记位

②关于权限

2 close

3 read 

4 write


文件操作这里实操的部分,我会先从C语言对应的接口入手,深入到OS的系统调用接口来进行讲解,其中会穿插一些概念性的东西,便于大家更好地理解和使用这些接口。

对文件操作无外乎这几个步骤:打开文件,操作文件(IO),关闭文件。这些接口也是根据这个思路来设计使用的。

一 C语言层面的文件操作

1 打开文件 fopen

参数:

打开文件需要找到文件并且指定打开方式。

第一个参数就是用来找到对应文件的,可以传入路径名+文件名;或者直接传入文件名。如果不指定路径,后续创建的文件默认是在当前工作目录下创建的。

第二个参数是打开的方式,有rwa等方式,r的话是只读,打开对应的已经存在的文件,wa的话是以读写的方式打开,如果文件存在,就打开;不存在就会去创建。不同的是w会在打开文件的时候清空文件,默认是从文件开头再写入文件。a的话不用对文件进行清空,但是会在末尾追加,不断地往文件中写入。

返回值:如果打开成功,返回FILE*类型,也被叫做文件指针,文件句柄。但是如果打开失败,返回NULL。

所以我们使用的时候,需要对返回值做判定,如果是NULL的话,后续操作也就没有意义了,可以直接退出进程。也可以把对应的错误原因打印出来开一下,需要调用perror接口。当文件打开失败的时候,errorno(错误码)就会被设置,调用perror的话,就可以根据错误码,打印出对应的错误原因。关于错误码在之前的进程控制的进程退出有讲到。

先来简单地试用一下fopen:

 上面只是让大家对fopen这个C语言库函数函数有个基本的认识,接下来我要再对上述概念中的当前目录和打开方式做重点讲解。

关于当前目录:

文件被打开其实是进程打开的,只有当程序运行起来成为进程的时候,对应的文件才会被进程通过系统接口来创建出来。基于此,当前目录其实就是进程的工作目录。cwd-》当前进程的工作目录。当一个进程运行起来的时候,每个进程都会记录自己当前所处的工作路径。log.txt是在cwd下创建的一个文件,即cwd路径+对应文件-》该文件的所在路径。所以myproc和log.txt会在一个层级关系上。

 2 fclose 关闭文件

fclose可以实现关闭文件的功能,传入对应的文件指针即可。

3 fwrite fprintf fputs

关于文件的写操作,有很多接口,C语言提供了fwrite,fprintf,fputs等接口,但是不管怎样都可以实现写的操作。只不过使用上有差异罢了。

①fwrite 

 第一个参数:想要写的字符串的起始地址,第二个参数:该字符串的基本单元,第三个参数:该字符串的基本单元的大小,第四个参数:文件指针,对应的往哪里写。第一个参数-》第四个参数中写入。

这里有一个需要注意的地方:该字符串的基本单元计算:

  • 写入的时候传参大小要不要+1呢?要不要把\0写入到文件中呢?以fwrite为例子

strlen(s1)

不需要。\0结尾是C语言对字符串的规定,文件不需要遵守。文件被写到磁盘上了,和语言层面已经没关系了。如果+1,写入到文件中的东西会多一个乱码。

文件中保存的是有效数据,即在字符串中,\0是标定字符串结尾的标识符,不是字符串本身的内容。因此文件操作不需要+1。

OS层面和语言层面的方案不同。读取的时候读取有效的,如果需要再+\0即可。

②fprintf

以格式化的形式往文件流中写入。对比printf,其实就多了一个参数,该参数指定了对应的串往哪里写。

③fputs

向特定的文件流中按行写入字符串

 

 第一个参数是需要被写入的串,第二个参数是该串需要往哪里写。第一个参数对应的内容-》第二个参数的位置

基本使用:

这样就实现了将对应内容写入到文件中的操作。

由于我是以w的方式打开,因此每次打开文件的时候都会将文件中的内容先清空。利用这个特性我们可以实现情况一个文件的操作。

 

 >输出重定向,他会先将文件打开之后再进行对应的操作。但是由于是以w的方式打开,之前写到文件中的东西就全部都被清空了。

讲了上述的一些写操作,我们来演示fopen中的以a方式打开。因为必须在了解写操作之后,才方便进行演示。

 仅仅将w-》a,每次运行进程,打开文件进行写入都不会清空,所以之前的内容一直被保存着。

4 fgets

读文件操作,以fgets为例子

 

按行读取为例子:fgets 读取的时候,第一个参数,提供缓冲区,放入你读到的数据,第二个缓冲区大小,第三个你想从哪里读取。结束如果失败返回null,成功就是你读到字符串的起始地址被返回。

fets自动在字符结尾添加\0,所以计算缓冲区大小的时候不用-1

 

 

 注意打开文件要以r的方式打开。fgets就是把对应文件中的东西放入到line中,直到文件结束。之后将line中的东西往stdout(显示器)上打印

模拟实现mycat

以上就是C语言库函数中文件操作的基本函数使用

二 系统接口的使用

C库函数和系统调用的关系:C库函数是语言层面接口,系统调用是OS的接口,语言在上,OS在下,C库函数一定会调用系统调用来实现。体系结构支撑我们理解软件知识。因此open-》fopen,write-》fwrite,read-》fread,close-》fclose

接下来就对系统层面的这些接口做介绍

1open

 有两个接口,区别在于是否传入权限。第一个参数和fopen一样理解,第二个代表的是选项,第三个代表权限。

关于选项:

 选项有很多。接下来主要对选项是什么,选项是如何传递的,以及选项如何使用,和C语言中的wra如何对于做解释。

①如何给函数传递标记位

数据结构中有一种结构叫做位图,其实原理和他差不多。

上述所有的选项其实是宏定义。一个标记位代表1个状态,标识1个选项。我们传入一个选项可以用bool,这种两态的标识。但是想传入多个呢?整数是有三十二个比特位的。可以传入多个标记位,每一个标记位对应占一个比特位,这样就可以实现传入多个标记位的目的了

主要是通过|&位操作来实现的,比如ONE是000 0001,那么传给show,进行&操作,如果标记位都想同才是1,ONE只有最低位是1,因此有ONE传入的话,if条件就是真的,可以执行对应的语句。

如果传入多个选项,|,那么只要有对应选项的比特位都被置成1了,接下来去执行&操作,每一个都会去判断,只有相应位置是1,才会执行对应的语句。比如同时传入ONE TWO 那么show接收到的就是0000 0011,他分别与0000 0001,0000 0010,0000 0100进行&操作分别是true true false,因此会分别执行ONE TWO对应的选项。

上层一个很简单的动作,底层可能要执行很多操作,比如w,需要传入O_WRONLY|O_CREAT|O_TRUNC三个选项,代表以读写方式打开,如果文件不存在就创建,并且需要对文件清空。

 如果需要以a的方式打开,只需要把O_TRUNC换成O_APPEND即可

②关于权限

Linux下由于有umask的作用,因此屏蔽了权限,如果我想对文件设置权限就可以在第三个位置传入权限。

2 close

包含对应的头文件把fd传入即可关闭文件

3 read 

 

 将fd对应的文件中的数据读取到buf中,大小是count

他没有类型,是以流或者字节的方式进行读取的。因此在read看来,读取的就是对应字节的数据。用sizeof计算。

 

4 write

 向fd中写入对应count大小的buf

接下来演示一下

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值