文件/目录管理(1)---open()/close()/read()/write()

一 文件管理

  在Linux中,几乎一切都被看成了文件,因此文件操作函数(系统调用):
  open()/close()/read()/write()/ioctl()
  可以操作几乎所有输入输出设备。

1 open()函数

open() 打开一个文件
int open(char* filename,int flag,…)

filename 表示文件名(带路径)
flag 是打开的标识,可以选择打开方式,常见值
  O_RDONLY  O_WRONLY  O_RDWR - 选择打开的权限
  O_CREAT - 如果不存在会新建,存在则打开
  O_TRUNC -和O_CREAT结合使用,打开时清空文件
  O_EXCL -和O_CREAT结合使用,但文件存在时不打开,而是返回 -1 代表错误
  O_APPEND - 追加的方式打开文件

… 代表0-n个任意类型的参数,如果是新建文件需要第三个参数,如果只是打开文件不需要第三个参数,新建文件时,第三个参数是新建文件的权限(必须)。

返回文件描述符,-1代表出错。
文件描述符本身就是一个非负整数,代表一个打开的文件。

文件open的过程
  先打开一个文件 -> 用文件表记录该文件信息 ->在文件描述符总表中,找没使用的文件描述符(默认找最小) -> 把最小的文件描述符和文件表对应起来,放入文件描述符总表中。

  文件描述符0 1 2被系统占用,分别代表标准输入、标准输出和标准错误,打开文件的描述符从3 开始。

open.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
  printf("O_RDONLY=%d,O_WRONLY=%d,O_RDWR=%d\n"
        ,O_RDONLY,O_WRONLY,O_RDWR);
  printf("O_CREAT=%d\n",O_CREAT);
  printf("O_APPEND=%d\n",O_APPEND);
  int fd = open("a.txt",O_CREAT|O_RDWR,0666);
  if(fd==-1) perror("open"),exit(-1);
  printf("fd=%d\n",fd);
  int fd2 = open("a.txt",O_RDONLY);
  printf("fd2=%d\n",fd2);
  close(fd); close(fd2);
}

2 read()和write()

read() 和 write() ,读数据和写数据
三个参数:
  第一个参数 fd
  第二个参数 void*
  第三个参数 read() 用sizeof(),write()用实际想写入的字节数

write.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
  int fd = open("a.txt",O_CREAT|O_RDWR,0666);
  if(fd==-1) perror("open"),exit(-1);
  int res = write(fd,"hello",5);
  if(res==-1) perror("write"),exit(-1);
  printf("写了%d字节数据\n",res);
  close(fd);//int fd2 = open("a.txt",O_RDONLY);//if(fd2==-1) perror("open"),exit(-1);
  char buf[100] = {};
  res = read(fd2,buf,sizeof(buf));
  if(res==-1) perror("read"),exit(-1);
  printf("读到了%d字节,内容:%s\n",res,buf);
  close(fd2);
}

下面是用read()和write()写的两个小练习。
1 实现文件的复制

copy.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
  //新建文件时,有预设的文件权限屏蔽(002),umask
  int fd = open("a.txt",O_RDONLY);//读文件
  if(fd==-1) 
      perror("open"),exit(-1);
  char buf[100] = {};
  int fd2 = open("b.txt",//写文件
        O_CREAT|O_RDWR|O_TRUNC,0666);//O_APPEND
  if(fd2==-1) perror("open2"),exit(-1);
  while(1){
      int res = read(fd,buf,sizeof(buf));
      if(res <= 0) break;
      write(fd2,buf,res);
    }
  close(fd);
  close(fd2);
}

2 把员工信息写入文件,并在另外一个文件中读出来

writeemp.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

struct emp{
  int id;
  char name[20];
  double sal;
};

int main(){
  int fd = open("emp.dat",
        O_CREAT|O_RDWR|O_TRUNC,0666);
  if(fd==-1) 
      perror("open"),exit(-1);
  struct emp em = {100,"zhangfei",12000.0};
  int res = write(fd,&em,sizeof(em));
  if(res==-1) perror("write"),exit(-1);
  printf("写入员工信息成功\n");
  close(fd);
}


reademp.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

struct emp{
  int id;
  char name[20];
  double sal;
};

int main(){
  int fd = open("emp.dat",O_RDONLY);
  if(fd==-1) 
      perror("open"),exit(-1);
  struct emp em;
  int res = read(fd,&em,sizeof(em));
  if(res==-1) 
      perror("read"),exit(-1);
  printf("%d,%s,%lf\n",em.id,em.name,em.sal);
  close(fd);
}

趣味练习:
  把员工信息写入文件,要求用cat/vi能看清楚信息
提示:
  只有字符串类型才能被vi看清楚。
  把员工信息拼接成一个很长的字符串再写入文件
  sprintf() 和printf() fprintf() 用法基本一样

empws.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

struct emp{
  int id;
  char name[20];
  double sal;
};

int main(){
  int fd = open("emp.dat",
        O_RDWR|O_CREAT|O_TRUNC,0666);
  if(fd==-1) perror("open"),exit(-1);
  struct emp em = {100,"zhangfei",12000.0};
  char buf[100] = {};
  sprintf(buf,"%d,%s,%lf",em.id,em.name,
        em.sal);
  write(fd,buf,strlen(buf));//不要使用sizeof
  close(fd);
}

  用vi来编辑文本文件时,会自动在文本末尾加上‘\n’,这个可以通过ls -l查看文件的大小来发现会多一个字节。而通过write向文件中写的则不会。

test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
  //新建文件时,有文件权限屏蔽(002)
  int fd = open("a.txt",O_CREAT|O_RDWR,0666);
  if(fd==-1) perror("open"),exit(-1);
  write(fd,"hello",5);
  close(fd);
}

3 字符串相关常用操作

这里来一个小插曲,总结一下有关字符串的一些操作:

string.c
#include <stdio.h>
#include <string.h>

//字符串的基本操作
int main(){
  //1 赋值 =和strcpy
  //2 指针操作 字符串以'\0'结尾,字符串数组以
  // NULL结束
  //3 字符串的拼接操作
  char buf[100] = {};
  char* s1 = "abc"; char* s2 = "def";
  strcpy(buf,s1);
  strcat(buf,s2);
  printf("%s\n",buf);
  //4 字符串和其他的类型转换(转换函数)
  //其他类型转字符串sprintf(); 
  //字符串转其他类型sscanf();
  int i = 12345;
  char bufint[12] = {};//最少12 负号+10位数+\0
  sprintf(bufint,"%d",i);
  printf("%s\n",bufint);
  char* st = "1234";//字符串转int
  int a;
  sscanf(st,"%d",&a);
  printf("a=%d\n",a);
  //5 其他相关函数,比如strlen() 取长度
  //strcmp()/strncmp() 比较字符串
}

4 关于标C函数和UC函数的区别

  标C函数都有输入/输出缓冲区,而UC函数在用户层是没有缓冲区,因此,频繁输入输出时,UC函数最好自定义一个缓冲区(char buf[])。
  如果对于性能没有特殊的要求,使用标C函数即可,有特殊要求,使用UC函数更好。

BiaocUc.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

//分别用标C和UC函数写100万个int
int main(){
  /*FILE* file = fopen("a.txt","w");//标C
  if(file==NULL) 
    perror("fopen"),exit(-1);
  int i=0;
  for(i=0;i<1000000;i++){
      fwrite(&i,4,1,file); //写int
      //fprintf(file,"%d",i);//转字符串后写
    }
  fclose(file);*/

  int fd = open("a.txt",
        O_RDWR|O_CREAT|O_TRUNC,0666);
  if(fd==-1) perror("open"),exit(-1);
  int i;
  int arr[10000] = {};
  for(i=0;i<1000000;i++){
      /*write(fd,&i,4);*/
      arr[i%10000] = i;
      if((i%10000) == 9999) 
      write(fd,arr,sizeof(arr));
   }
  close(fd);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值