Linux下IO编程(一)

Linux下IO编程

文件IO

open函数——打开or创建一个文件

#include <fcntl.h> //open函数在此头文件中声明
int open(const char *pathname, int flags, mode_t mode)

参数意义如下:

  • pathname——文件路径
  • flags ——打开文件的方式
  • mode——创建文件的权限(可省略)

flags的内容如下:

flags功能
O_RDONLY只读打开
O_WRONLY只写打开
O_RDWR读写打开
O_CREAT若路径中的文件不存在则自动建立该文件
O_APPEND读写文件从文件尾部开始移动,所写入
O_TRUNC打开文件,会把已经存在的内容删除
O_EXCLO_CREAT |O_EXCL指令会去检查文件是否存在,文件若不存在则建立,否则返回-1

mode的表示方法1:

mode功能
S_IRUSR所有者拥有读权限
S_IWUSR所有者拥有写权限
S_IXUSR所有者拥有执行权限
S_IRGRP群组拥有读权限
S_IWGRP群组拥有写权限
S_IXGRP群组拥有执行权限
S_IROTH其他用户拥有读权限

mode的表示方法2:——可以由3位数字组成(umask)

数值第一位第二位第三位
4(读)所有者群组其他用户
2(写)
1(执行)

函数返回值

函数的返回值是文件描述符,如果打开文件成功返回一个正整数,否则返回-1。文件描述符,是一个非负的整数,相当于文件的ID号。

举例:通过open函数实现touch功能

#include <stdio.h>							// 提供open()函数  
#include <fcntl.h>
#include <unistd.h>                        // 提供close()函数  
int main(int argc,char* argv[])
{
        int fd;
        fd =open(argv[1],O_CREAT | O_RDWR,0777);
        if(fd<0)
        {
                printf("create file %s is failed\n",argv[1]);
                return -1;
        }
        else
        {
                printf("create file %s is sucess,fd is %d\n",argv[1],fd);
        }
        close(fd);
        return 0;
}

write函数

#include <unistd.h>
ssize_t write (int fd, const void * buf, size_t count); 

参数

  • fd——文件描述符
  • buf——写入内容
  • cout——向文件中写多少(字节)

函数返回值:返回实际写入的字节数。

举例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
        int fd;
        int wr_ret;
        char buf[]="hello linux";
        fd=open("./a.c",O_TRUNC |O_RDWR);
        if(fd<0)
        {
                printf("open file is failed");
                return -1;
        }
        printf("open file is success ,fd is %d\n",fd);
        wr_ret=write(fd,buf,sizeof(buf));
		printf("the wr_ret is %d\n",wr_ret);			//12个字节 加上“\0”
        close(fd);
        return 0;
}

read函数

#include <unistd.h>
ssize_t read(int fd, void * buf, size_t count);

函数说明:

read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。

返回值:返回值为实际读取到的字节数

注意:

  1. 先写再读会涉及一个指针读写位置指针,在写完的指针位置进行读会读不到内容,如下举例
  2. read时fd中的数据如果小于要读取的数据,就会引起阻塞,详见:https://blog.csdn.net/hhhlizhao/article/details/71552588

举例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
        int fd;
        int wr_ret,rd_ret;
        char buf[]="hello linux";
        char rd_buf[]={0};
        fd=open("./a.c",O_TRUNC |O_RDWR);
        if(fd<0)
        {
                printf("open file is failed");
                return -1;
        }
        printf("open file is success ,fd is %d\n",fd);
        wr_ret=write(fd,buf,sizeof(buf));
        printf("the wr_ret is %d\n",wr_ret);
        //read
        rd_ret=read(fd,rd_buf,128);
        printf("the rd_ret is %d,the rd_buf is %s\n",rd_ret,rd_buf);
        close(fd);
        return 0;
}
//以上输出为
open file is success ,fd is 3
the wr_ret is 12
the rd_ret is 0,the rd_buf is  //发现读不到

lseek函数

#include <sys/types.h>
#include <unistd.h>
off_t  lseek(int fd, off_t offset, int whence)

函数作用:

用于移动文件读写指针,因此还有以下两种作用:

  • 扩展文件;
  • 获取文件大小;lseek(fd,0,SEEK_END)

参数

  • fd——文件描述符
  • offset——相对基准的偏移量,字节为单位,为正则向文件末尾移动(向前移),为负数则向文件头部(向后移)
  • whence——当前的基准

whence主要有3个标志:

whence说明
SEEK_SET从文件头部开始偏移offset个字节
SEEK_CUR从文件当前读写的指针位置开始,增加offset个字节的偏移量
SEEK_END从文件结尾开始,文件偏移量设置为文件的大小加上偏移量字节

返回值:成功,返回从文件开头到当前结束位置的偏移量(1字节为单位);失败返回-1。

举例1:对上个例子应用lseek()将读写指针移到开头,来实现先写再读

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
        int fd;
        int wr_ret,rd_ret;
        char buf[]="hello linux";
        char rd_buf[]={0};
        fd=open("./a.c",O_TRUNC |O_RDWR);
        if(fd<0)
        {
                printf("open file is failed");
                return -1;
        }
        printf("open file is success ,fd is %d\n",fd);
        wr_ret=write(fd,buf,sizeof(buf));
        printf("the wr_ret is %d\n",wr_ret);
        //start read 
        lseek(fd,0,SEEK_SET);   //<========================================
        rd_ret=read(fd,rd_buf,128);
        printf("the rd_ret is %d,the rd_buf is %s\n",rd_ret,rd_buf);
        close(fd);
        return 0;
}
//经过lseek()函数调整读写指针位置后
open file is success ,fd is 3
the wr_ret is 12
the rd_ret is 12,the rd_buf is hello linux

举例2:综合应用——使用以上所学完成类似cp操作

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char* argv[])
{
        int rd_fd,wr_fd;
        int rd_ret;
        int wr_ret;
        char read_buf[128]={0};
        if(argc<3)
        {
                printf("are you kiding me? ");
                return -1;
        }
        rd_fd=open(argv[1],O_RDONLY);
        if(rd_fd<0)
        {
                printf("open the src file:%s  is failed\n",argv[1]);
                return -2;
        }
        printf("open the %s is sucessful\n",argv[1]);
        wr_fd=open(argv[2],O_WRONLY);
		if(wr_fd<0)
        {
                printf("open the des file:%s is failed\n",argv[2]);
                return -3;
        }
        printf("open the %s is sucessful\n",argv[2]);
        while(1)
        {
                rd_ret=read(rd_fd,read_buf,128);         //read时有读写指针
                wr_ret=write(wr_fd,read_buf,rd_ret);     //所以此处一次读不完但是也能连续
                if(rd_ret<128)
                {
                        break;
                }
                memset(read_buf,0,128);
        }
        close(wr_fd);
        close(rd_fd);
        return 0;

}

注:

  1. 从文件向buf中read时,因为文件有读写指针,并且一次循环read完一个buf马上进行write,所以最终得到的内容是连续的。但是要注意write函数,write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。

    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    int main(int argc,char* argv[])
    {
            int wr_fd;
            int wr_ret;
            char buf[]="hello linux";
            wr_fd=open(argv[1],O_CREAT |O_RDWR,0666);
            if(wr_fd<0)
            {
                    printf("open the file is failed");
                    return -1;
            }
            wr_ret=write(wr_fd,buf,2); 
            wr_ret=write(wr_fd,buf,2);//写两次结果可能为“hehe” or "hell"
            close(wr_fd);
            return 0;
    }               
    
    //编译后执行
    ./test test.c 
    得到test.c文件中内容为“hehe”
    

    可按如下格式实现buf读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。

    int main()
    {
      char *p1 = "This is a c test code";
      volatile int len = 0;
     
      int fp = open("/home/test.txt", O_RDWR|O_CREAT);
      for(;;)
      {
         int n;
     	 n=write(fp, p1+len, (strlen(p1)-len);
         if(n== 0)   
         {                                                 
             printf("n = %d \n", n);
             break;
         }
         len+=n;       
      }
      return 0;
    
  2. 以上例子还未用到lseek()函数,因为以上函数是直接cp复制一个编辑好的文件,而不是复制通过write函数写出的文件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值