【Linux】文件操作(一)

这篇具有很好参考价值的文章主要介绍了【Linux】文件操作(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

预备知识

复习C语言文件接口

fopen()

写入类:fwrite()、fprintf()、fputs()

读取类:fgets()

系统接口

open()

一个参数如何传递多个选项?

close()

write()

read()


 文章来源地址https://www.toymoban.com/news/detail-601015.html

预备知识

在正式讲解文件之前,我们需要有一些预备知识:


1.文件 = 文件内容 + 文件属性.


2.对文件操作:1.对内容操作 2.对属性操作


3.文件在磁盘(硬件)上,我们访问文件流程是什么呢?

先写访问文件的代码 ->编译->exe可执行程序->运行->访问到文件.

访问文件本质是进程在访问文件。而进程访问文件是需要接口的.我们目前所学到的接口都是一些语言接口,而不是系统接口.

磁盘是一种硬件,想要在硬件中写入,只有操作系统有权限。如果普通用户也想写入,那么操作系统必须提供文件系统调用的接口.

而我们平常使用的C语言的文件操作的相关接口都是对系统接口的封装,这样会使用户对接口更方便,简单的使用.

但是这样,会导致每个语言例如(C++和Iava)的文件操作的接口不相同,但是底层都是系统接口,因为这样的接口只有一套,只不过是封装方式不同。

封装的好处是可以跨平台运行代码(比如利用条件编译,动态裁剪),如果用户直接使用系统接口,换一个平台代码便运行不了了.


4.显示器是一种硬件,在linux下本质上是一个文件!printf向显示器打印,本质上也是一种写入;和在磁盘中向文件中写入是一样的!


5.Linux下,一切皆文件.我们现在对其只能有个理性的认识.

曾经我们理解的文件:read读取,write写入.

显示器:printf/cout ->一种写入

键盘:scanf/cin ->一种读取

以上都是站在我们写的程序的角度来说,将来我们的程序要加载到内存,相当于我们站在内存的角度,键盘相当于把我们的数据输交给内存(input),而内存把读取到的数据刷新到文件或者显示器当中(output)。

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open 这就相当于是一次IO操作.

 我们在回过头来,什么叫做文件呢?

站在系统的角度,能够被input读取,或者能够output写出的设备就叫做文件.

狭义上的文件:普通的磁盘文件

广义上的文件:显示器,网卡,声卡,显卡,磁盘等等,几乎所有的外设,都可称之为文件。    

复习C语言文件接口

fopen()

我们先使用man fopen 来查看一下函数的用法

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 这个函数用来打开文件的,

        1.FIFE* 我们称为文件指针。

        2.其中第一个参数是要被打开函数的路径

        3.第二个参数是打开模式,即以什么样的方式打开.一共有6种:

r(读):对文件只进行读操作


r+(读和写):对文件进行读和写操作.


w(读):先把文件内容清空,然后从文件开始进行写入操作.若文件不存在,则创建一个新文件.


w+(读和写):先把文件内容清空,然后可以问对文件进行读和写操作,若文件不存在,则创建一个新文件。


a(写):向文件结尾处开始写,相当于追加操作。若文件不存在,则会创建一个新文件.

a+(读和写):从文件结尾处开始写,文件开头处开始读,若文件不存在,则会创建一个新文件.

r是读取文件,这个在我先讲解完w(写)之后,然后讲解会方便一些.

我们看一下w:首先在vim中编写如下代码

#include<stdio.h>    
    
int main()    
{    
  FILE* fp = fopen("log.txt","w");    
  if(fp == NULL)    
  {    
    perror("fopen");    
    return 1;    
  }    
  //进行文件操作                                                                                                                                       
  fclose(fp);    
                                                                                                                                             
  return 0;                                                                                                                                  
}     

 这个我们使用了w模式打开,并且我们当前路径下并没有“log.txt”这个文件.

我们退出make编译,然后运行

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 这样因为原来文件不存在,所以会自动帮我们创建一个新文件.

那么问题是:我代码中只写了一个log.txt,那么是如何知道它在哪或者在哪创建呢?

当一个进程运行起来的时候,每个进程都会记录自己当前所处的工作路径!这个路径就叫做当前路径,log.txt的查找与创建都是在当前路径中进行的.


然后如果我们此时向log.txt文件中写入一些内容,然后再以w模式运行程序,会发生什么呢? 

以w模式打开文件【Linux】文件操作(一),linux,服务器,write,read,文件操作,open 

 然后向文件中输入“hello,world”并运行. 

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 我们发现一开始log.txt中还有内容,然后以w方式运行程序后,里面的内容就被清空了.

这就验证了我们刚才所说的w模式会在写入之前将文件内容清空.

那如果我们如果不想让文件被清空,而是接着文件后面的内容写呢?这个时候需要用a/a+模式进行打开.

这个写的接口fwrite我们马上讲,知道这个是向文件中写入就好了

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

然后我们退出来,编译运行: 

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

发现每一次运行并不会将文件清空,而是追加在后面继续写.

写入类:fwrite()、fprintf()、fputs()

我们刚才打开了文件,相应的就要对文件进行操作了,这是fwrite的用法:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

         1.第一个参数ptr是指向要被写入的元素数组的指针。

         2.第二个参数size是每个元素的大小,字节为单位.

         3.第三个参数是元素的个数,每个元素的大小为size字节

         4.第四个参数为FILE指针,即fopen()打开文件之后返回的文件指针.

在代码中,我们这么写:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open 

 因为s1是一个字符串,所以strlen直接计算了整个字符串的大小,所以第三个参数只传入1即可,大小为整个字符串的大小.

此时我们输出log.txt便成功写入到文件了

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 


然后介绍一下fprintf()的用法,函数原型为:

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

        1.第一个参数还是为文件指针。

        2.第二个参数就是我们正常的格式化输出。

用代码写入的时候,这样写

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 然后便也成功的写入到文件当中了:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open


fputs同样地也是向文件中写入,函数原型是

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

        1.第一个参数为我们要写入的字符串内容.

        2.第二个参数还是文件指针.即一开始的fp.

我们用一下,也比较简单

 【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open 

 这样便成功写入到文件了.


读取类:fgets()

同样地,我们先来看一下函数原型:

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

        1.第一个参数s是输出型参数,会把读取的结果存放在s指向的字符数组里.

        2.第二个参数size是读取的最大字节数,如果文件内容本身小于size,那么只读取文件内容,如果大于则读取size个字节

        3.第三个同样是文件指针,通过fopen()得到的.

看一下它的返回值:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 fgets()如果返回成功,则返回s,失败的话返回NULL.


具体是怎么使用呢?

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 然后我们此时log.txt文件中是已经有内容的,我们运行程序便可以看到内容被输出了

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 上面代码我们提到了stdout,这个是叫做标准输出流

执行程序时,我们C语言会默认打开三个标准输入输出流:

        1.stdin 标准输入,对应键盘

        2.stdout 标准输出,显示器

        3.stderr 标准错误, 显示器

我们用man stdin来看一下它.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 发现类型是文件指针,其实这也变相的说明了一个道理:linux下一切皆文件!

但是如何理解这些,还是个问题,我们讲解完系统接口之后,相信再回来理解就会透彻很多.

系统接口

这里系统接口一共有4个:open,close,read,write

open()

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

它的作用是打开 并且可能创建一个文件或设备.暂时理解为打开文件即可.

        1.第一个参数pathname,和刚才得接口一样,都是要打开的文件路径

        2.第二个参数flags是一些选项,它的选项非常多,这里会挑一些常用的讲解.

        3.第三个参数等下会说.

对于第二个参数:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

flags中必须包含以上三个中的其中一个,分别代表O_RDONLY(read only只读),O_WRONLY(write only 只写),以及O_RDWR(read write读和写).

 然后后面可以再添加别的选项.那么只有一个flags参数,怎么传入很多的选项呢?

一个参数如何传递多个选项?

这里采用了位操作:即用int中不重复的一个bit位,就可以标识一种状态.

例如0000 0001可以表示一种状态,0000 0010表示第二种状态,以此类推。

当我们需要检测有没有第一种状态时,我们可以让flag此时&0x1(0000 0001),这个时候,如果结果为1,说明flag的最后一位有1,那么就代表它有这个选项,便执行对应的操作.

同样的,检测是否有第二种状态,只需继续判断flag&0x2(0000 0010)==1。如果等于,说明flag的倒数第二位有1,否则没有.

那么如何让flag同时拥有这两种状态呢(即如何同时传入两个选项)?

我们只需要让两个状态 |(按位或) 一下即可.假设

#define ONE 0X1 // 0000 0001
#define TWO 0X2 // 0000 0010

然后 flag = ONE | TWO,此时flag的位便是 0000 0011

然后我们再判断flag,此时flag & 0x1 = 1,说明有第一个选项;flag & 0x2 = 1,也说明有第二个选项,这样我们就相当于传入了多个选项了.


我们使用简易的代码来完成一下这个操作.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

此时我们期待的结果应该是输出1,3和1,2,3.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

此时便得到了我们想要的结果了,也顺便成就了一个参数里面传递多个选项.


同样地,回到open上,它的flags中很多选项虽然是是大写,但也是定义的宏,本质上也是数字,然后分别用不同的比特位标识.

然后我们再看一下open的返回值:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 可以看到open如果成功便返回一个新的文件描述符,失败则返回-1.

这个文件描述符我们下一章会详细讲解.现在你只要知道文件描述符是个整型即可.


知道了以上这些,我们开始用用open这系统接口吧.首先以只写的方式打开.

int main()    
{    
  int fd = open("log.txt",O_WRONLY);    
  if(fd < 0)    
  {    
    perror("open");    
    return 1;    
  }    
  //open successful    
  printf("open success,fd: %d\n",fd);    
}            

我们此时目录下并没有log.txt文件,c语言那个fopen接口,只写的话如果没有文件会给我们创建一个新的文件,那系统接口会吗?

我们编译运行一下:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

我们发现说系统找不到这个文件,由此说明,系统只写这个接口是不会直接给我们创建新的文件的,而c语言之所以可以,是因为对系统接口进行了封装,简化了我们的使用.

其实你在应用层看到的一个很简单的动作,在系统接口或者OS层面,可能都需要做很多的工作

所以如果文件不存在想创建一个呢?这个时候便需要再传入一个选项O_CREATE.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

然后我们将它按照上面所讲的,传递两个选项,则将两个选项 | 一下.

int fd = open("log.txt",O_WRONLY | O_CREAT);

 【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

此时我们便成功打开了.


但是,我们看一下我们创建好的文件的权限:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

怎么会是这样的呢?我们不想要这样的,如果我们想指定权限该怎么做呢?

这就回到了我们刚开始讲open的时候第三个参数mode,它便是创建新文件时,赋予文件的权限.

比如我们给文件的权限是0666 .

int fd = open("log.txt",O_CREAT | O_WRONLY,0666); 

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

这样,这个权限总算看着正常一点,但是怎么会少一个呢?

我们理想的是-rw-rw-rw,这个怎么是-rw-rw-r--呢,少的一个w去哪了?

这是由于掩码umask的存在,我在之前文章的权限的理解里详细的说过。

默认掩码是002,而每个权限又不能和掩码中的比特位为1的位相同,002中2的比特位是010,不能和第二个值为1的位一样,所以只能将w权限去掉,因为w正是对应的第二个比特位.

我们可以在程序里,将这个进程的umask设为0,然后便解决了问题.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

此时便得到了正确的结果:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

close()

这个接口比较简单,就直接把文件描述符传进去,然后关闭了文件即可.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

write()

先来看write的用法

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 函数原型:

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

        1.fd为open()返回的文件描述符.

        2.buf为要写入的内容

        3.count为向文件中写入多少字节.

我们直接用代码来演示:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 此时我们退出,编译运行

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

我们发现此时已经成功写入了. 

如果此时我们把写入的内容换一下:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

然后再次运行:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

我们发现原来的hello,write没有被清空,而abcd是直接从头开始写的,然后把原来的一部分内容给覆盖了.我们如果想清空内容,就需要用到一个新的选项:O_TRUNC

 【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

这个选项会讲原文件内容清空. 所以我们把open代码中加上这个选项:

int fd = open("log.txt",O_CREAT | O_WRONLY | O_TRUNC,0666); 

然后再次退出make编译运行:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

发现此时原文件的内容已经被清空,然后写入了abcd.


如果我们想追加内容,即不清空,直接在文件后面继续写,我们把O_TRUNC换成O_APPEND即可. 这个便不再继续演示了.

read()

还是先来查看用法:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

函数用法和write的非常类似,只不过把文件的内容读到buf,相当于buf成了输出型参数,读取的字节数是count.

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open最后read的内容会写在buffer中,然后我们最后输出它即可.

 我们在log.txt文件中编辑以下内容:

【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 然后编译运行程序:

 【Linux】文件操作(一),linux,服务器,write,read,文件操作,open

 便成功读取出来了.

关于文件操作的一部分内容便到这结束了,下一章我们将真正迈入文件的范畴,开始讲解文件描述符等相关的一系列知识.

 

到了这里,关于【Linux】文件操作(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux 操作系统安装 Apache 服务器

    摘要 电子计算机诞生以来,计算机操作系统的研究有了很大的发展。我们 身边最熟悉的操作系统有微软的 windows。当然这只是相对于 pc 端来说。现在 操作系统进入了社会生活的各个方面,涉及大型计算机、个人计算机、移动便携 设备、其他自动化设备等各个层次的应用领域

    2024年02月04日
    浏览(66)
  • linux服务器文件实时同步

    在做系统集群部署时,涉及到两个或多个服务器之间文件同步.在软件层面linux服务环境找到以下两种同步方式 利用linux NFS功能将网络共享文件挂载成本地目录 采用文件监听,实时推送 服务器资源如下 服务器1 10.2.4.51 ,作为主服务器 服务器2 10.2.4.52 ,作为从服务器 2.1 主服务器

    2024年03月09日
    浏览(70)
  • linux服务器间文件传输

            当对服务器应用或文件进行迁移时,一般的方法是找一台电脑,先把文件从A服务器下载到电脑,然后再从电脑上传到B服务器。但这样传有几个问题:         1、步骤繁琐,必须通过电脑作为中介         2、需要安装额外的软件,比如winscp、FileZilla 等传输工具  

    2024年02月10日
    浏览(49)
  • Linux服务器移动文件命令

    mv(move) 命令可以将文件和目录从一个位置 移动 到另一个位置;         它也可以用来 重命名 文件和目录。 mv命令语法         source 可以是一个或多个文件或目录;         destination 总是一个文件或目录;         如果我们以单个文件为源,以一个目录为目标

    2023年04月25日
    浏览(61)
  • 【Linux】FTP文件服务器

    FTP (File transfer protocol) 是TCP/IP 协议组中的协议之一。他最主要的功能是在服务器与客户端之间进行文件的传输。FTP就是实现两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载 (download)”文件。将文件从自己计算机中拷贝至远程计算机上,则称

    2024年02月10日
    浏览(60)
  • Java中将本服务器的文件拷贝到另一个服务器(Linux to Linux)

    在Java中,将文件从一个服务器复制到另一个服务器,你可以使用Secure Copy(SCP)进行操作。Java中的 JSch 库可以进行此操作。 首先,需要添加 JSch 库依赖到你的项目中。如果你使用的是Maven,可以添加以下依赖: 以下是一个使用 JSch 进行SCP操作的示例: 这段代码首先创建了一

    2024年02月13日
    浏览(64)
  • 【Linux】搭建SFTP文件服务器

    1.11 特点 FTP(File Transfer Protocol)是一种用于在计算机之间传输文件的标准网络协议。它提供了一种简单而常用的方式来上传和下载文件,以及进行文件管理操作。 FTP协议的主要特点包括: 客户端-服务器架构 :FTP使用客户端-服务器模型,其中客户端是发送文件请求的一方,

    2024年02月07日
    浏览(41)
  • Linux文件写入操作:write函数的使用

    write函数定义 :write函数是基于Linux系统中的一项函数调用,主要用于在打开/创建的文件中 写入数据。 write函数包含的头文件 : write函数的格式原型 : write函数中的三项参数 : ① int fd open一个文件,就会返回到文件描述符中,对文件后续的操作都需要用到文件描述符。 ②

    2024年02月01日
    浏览(49)
  • 【运维】Linux 跨服务器复制文件文件夹

    如果是云服务 建议用内网ip scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时,用scp可以帮你把文件移出来

    2024年02月08日
    浏览(74)
  • 文件预览服务器kkfileview(linux部署)

    1、前置环境 2、安装kkfileview 官网地址:https://kkfileview.keking.cn/zh-cn/docs/home.html 3、安装office组件(报错提示:启动office组件失败,请检查office组件是否可用) 4、安装成功如图所示 5、查看office组件版本 6、配置kkfileview参数 7、启动文件预览服务 8、关闭文件预览服务 9、查看日志

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包