【Linux操作系统】-- 基础IO

目录

回顾C文件接口

写操作

读操作

追加操作

stdin & stdout & stderr

系统文件I/O

 系统调用接口open

 open函数返回值

文件描述符fd

输出重定向

  0 & 1 & 2

重定向

追加重定向

输入重定向

 使用 dup2 系统调用

缓冲区


回顾C文件接口

写操作

int fputs(const char *s, FILE *stream);将字符串写入文件

[wjy@VM-24-9-centos 27]$ cat myfile.c
#include <stdio.h>

int main()
{
  FILE* fp=fopen("./log.txt","w"); 
  // 在当前目录创建文件,打开方式为w
  //打开文件成功返回文件指针,失败返回nullptr
  if(NULL==fp)
  {
    perror("fopen");
    return 1;
  }

  int cnt=10;
  while(cnt--)
  {
    const char* msg="hello world\n";
    fputs(msg,fp);
  }

  fclose(fp);

  return 0;
}

或者用write写入也可以

write(fd,msg,strlen(msg));//将msg信息写入fd文件

如果用write写入,就要加入写入文件的大小 。在我们写入文件的过程中,我们需要写入\0吗?

不需要,\0作为字符串的结束,只是C的规定。文件关心的是字符串的内容,\0是文件结束的标志位,并非我们需要写入的内容。所以不需要将\0写进去。

读操作

w和r默认都是文本读写,如果要二进制写入是wb和rb

char *fgets(char *s, int size, FILE *stream);向s字符串写入文件,size是文件大小

因为C没有像C++的getline直接从文件读取到显示器上,所以只能用fgets将文件写入字符串,再打印出来。

int main()
{
  FILE* fp=fopen("./log.txt","r");//读,读入显示器
  if(fp==NULL)
  {
    perror("fopen");
    return 1;
  }
  char buffer[64];//缓冲区--向缓冲区读入
  while(fgets(buffer,sizeof(buffer),fp))//将缓冲区内容打印到显示器上
  {
    printf("%s",buffer);
  }

  if(!feof(fp))
    printf("fgets quit not normal!\n");
  else 
    printf("fgets quit normal!\n");
}
//显示结果
[wjy@VM-24-9-centos 27]$ ./myfile
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
fgets quit normal!

除了fgets还有read函数

为什么从fd文件中读入buffer缓冲区大小要-1呢?因为文件中的字符串写入的时候就没有写入\0,但是如果要从文件中读取出来还要加\0,但是我们不能读出这个\0,所以到小要-1。

为什么read的返回值是int(是读出字符串大小)?在read的参数列表中已经有了读出字符串大小,那么我们不是已经知道字符串的大小,这不是多此一举吗?       其实并不是,参数列表中的大小是想要读出的大小,而实际可能因为缓冲区大小不够,实际没有想要的大小。所以返回值返回的是实际读出数据的大小。

  int fd=open("./log.txt",O_RDONLY);
  if(fd<0)
  {
    perror("open");
  }

  char buffer[1024];
  ssize_t s=read(fd,buffer,sizeof(buffer)-1);
  if(s>0)
  {
    buffer[s]=0;
    printf("%s\n",buffer);
  }
  close(fd);

追加操作

w和a都一样,都要向文件中写入文本。但是w-write在写入之前会把文件都清空,然后再写入。而a-append追加,是在原有文件基础上继续写入文件,不会清空。其他原理都和w一样。

我们将原来文件删除后,再查看,随着每一次的追加写入,log.txt的内容都在增加

int main()
{
  FILE* fp=fopen("./log.txt","a");
  if(fp==NULL){
    perror("fopen");
    return 1;
  }

  const char* msg="hello world\n";
  int cnt=3;
  while(cnt--)
  {
    fputs(msg,fp);
  }
  fclose(fp);
}


//运行结果
[wjy@VM-24-9-centos 27]$ ./myfile
[wjy@VM-24-9-centos 27]$ cat log.txt
hello world
hello world
hello world
[wjy@VM-24-9-centos 27]$ ./myfile
[wjy@VM-24-9-centos 27]$ cat log.txt
hello world
hello world
hello world
hello world
hello world
hello world

stdin & stdout & stderr

如果学习文件操作,只停留在语言层面上,是很难对文件有一个深刻理解的!C程序默认会打开三个输入输出流:stdin,stdout,stderr。这些接口用man手册查看,都是FILE*类型,它是C语言的结构,说明C语言将这三个接口都归类为文件。

        stdin:键盘;stdout:显示器;stderr:显示器。


fputs(const char *s, FILE *stream)这个函数,是把第一个字符串s写入到第二个文件流当中的,因为stdout也是FILE*文件类型的,所以也可以将字符串写入到输入输出流中。

下面两张图片中,向stdout中写入内容,再将stdout中内容重定向到log.txt文件,发现文件重定向成功。但是向stderr中写入字符串,再用重定向将内容写到log.txt中,没有把内容写到文件中,字符串依旧显示在显示器上。所以,在linux命令行当中,输出重定向本质上是将stdout内容重定向到文件中。虽然都是向显示器中显示,但是stderr和stdout是不一样的。

 fputs向一般文件或硬件设备都能写入!硬件包括键盘、显示器;一般文件如log.txt是在磁盘上的,它的本质也是硬件。

系统文件I/O

我们写的程序最终都是要访问硬件:显示器,键盘,文件(磁盘)这些东西的。那么OS(操作系统就是硬件的管理者)。但是用户/语言,程序,lib不能直接访问硬件,也不能直接访问驱动,也不能直接访问OS。所以,所有的语言上的对“文件”的操作,都必须贯穿OS!

我们知道OS对外界是不公开的,操作系统不相信任何人,如果要访问操作系统,需要通过系统调用接口

几乎所有的语言fopen,fclose,fread,fwrite,fgets,fputs,fgetc,fputc等底层一定需要使用OS提供的接口调用。所有的语言要在操作系统上跑,一定要用统一的接口。

 系统调用接口open

open这个系统调用接口的头文件,以及传参形式。pathname代表要打开的文件;flags代表以什么形式打开文件,有w,r,a等;mode可以设立对应文件的权限信息。就比如ll查看文件信息,-rwxrwxr-x就是mode设置的默认信息。返回值是一个整数,文档中描述:return  the  new file descriptor, or -1 if an

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值