7.30IO进程线程

笔记

IO

三.文件IO

3.1文件描述符

        1> 文件描述符本质上是一个整数,当文件存储在本地磁盘时,属于静态文件。当使用open函数打开文件时,该文件就属于动态文件,后期需要对文件进行操作的话,需要基于一个句柄来完成。这个句柄就是文件描述符,用一个整数表示。

        2> 文件描述符是一个非负整数,一个进程能够使用的文件描述符默认为1024个。【0,1023】,可以通过指令 ulimit -a查看,并且可以通过ulimit -n进行修改进程能够打开的文件描述符个数

        3> 使用原则:最小未分配原则

        4> 特殊的文件描述符:0、1、2,分别对应了标准输入、标准输出、标准出错

stdin->_fileno     ===>   0    ===> STDIN_FILENO
stdout->_fileno    ===>  1    ===> STDOUT_FILENO
stderr->_fileno    ===>  2    ===> STDERR_FILENO

#include<myhead.h>

int main(int argc, const char *argv[])
{
    printf("stdin->_fileno = %d\n", stdin->_fileno);         //0
    printf("stdout->_fileno = %d\n", stdout->_fileno);       //1
    printf("stderr->_fileno = %d\n", stderr->_fileno);       //2

    FILE *fp = NULL;
    if((fp = fopen("./file.txt", "w")) == NULL)
    {
        perror("fopen error");
        return -1;
    }

    printf("fp->_fileno = %d\n", fp->_fileno);       //3 最小未分配
    


    return 0;
}
3.2open打开文件
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);
        功能:以指定的方式打开指定的文件
        参数1:要打开的文件路径
        参数2:文件打开标识
            必须包含以下三者之一:
                O_RDONLY:以只读的形式打开文件
                O_WRONLY:以只写的形式打开文件
                O_RDWR:以读写的形式打开文件
            以下的可以选择性加入,使用位或完成:
                O_CREAT:如果文件存在,就直接打开,如果文件不存在,则创建文件,此时,参数3必须要加,表示创建的文件权限
                O_TRUNC:表示清空文件内容
                O_APPEND:以追加的形式打开文件
                O_EXCL:确保打开的是不存在的文件,通常跟O_CREAT一起使用,表示本次操作必须创建新文件,如果文件存在,则open函数报错,错误码为:EEXIST
        ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
                "r":O_RDONLY
                "r+":O_RDWR
                "w":O_WRONLY|O_CREAT|O_TRUNC
                "w+":O_RDWR|O_CREAT|O_TRUNC
                "a":O_WRONLY|O_APPEND|O_CREAT
                "a+":O_RDWR|O_APPEND|O_CREAT
       ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
       参数3:当参数2中有O_CREAT属性时,参数3必须加上,表示本次创建文件的文件权限,但是,最终的权限不是用户给定的权限
           文件最终的权限是 给定的权限mode&~umask的值
           umask可以通过指令umask进行查看当前终端的默认掩码
           可以通过 umask -n   来将掩码更改成 n,但是,这种方式更改的umask只在当前终端有效,其他终端无效
           也可以通过umask(n)来更改umask的值
                  #include <sys/stat.h>

               mode_t umask(mode_t cmask);
               功能:更改当前的umask的值
               参数:要更改的umask的值
            普通文件权限一般为:0664
            目录文件权限一般为:0775
         ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
         返回值:成功返回一个新的文件描述符,失败返回-1并置位错误码  
3.3close关闭文件
       #include <unistd.h>

       int close(int fd);
    功能:关闭文件描述符
    参数:要关闭的文件描述符
    返回值:成功返回0,失败返回-1并置位错误码
    

#include<myhead.h>

int main(int argc, const char *argv[])
{

    //创建一个文件描述符变量,用于存储文件描述符
    int fd = -1;
    if((fd = open("./file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0664)) == -1)
    {
        perror("open error");
        return -1;
    }

    printf("open success fd = %d\n", fd);     //3


    //关闭文件
    if(close(fd) == -1)
    {
        perror("close fd 1");
        return -1;
    }


    return 0;
}
3.4read\write数据读写
 #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);
    功能:向指定的文件中,写入指定的信息
    参数1:已打开的文件描述符
    参数2:要写入的数据的起始地址
    参数3:要写入的数据大小
    返回值:成功返回写入字符的个数,失败返回-1并置位错误码
    
           #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
    功能:从指定的文件中读取count个字节的数据到buf中
    参数1:打开的文件描述符
    参数2:要存放数据的容器起始地址
    参数3:要读取的字节个数
    返回值:成功返回读取字节的个数,失败返回-1并置位错误码

#include<myhead.h>
//定义结构体类型
typedef struct 
{
    char name[20];
    int age; 
    double score;
}Stu;

/*********************主程序*************************/
int main(int argc, const char *argv[])
{

    //创建一个文件描述符变量,用于存储文件描述符
    int fd = -1;
    if((fd = open("./file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0664)) == -1)
    {
        perror("open error");
        return -1;
    }

    printf("open success fd = %d\n", fd);     //3

    //定义三个学生
    Stu s[3] = {{"zhangsan", 10, 99.5},\
                {"lisi", 15, 88},\
                {"wangwu", 8, 60}};
    //将所有学生写入文件中
    write(fd, s, sizeof(s));

    //关闭文件
    if(close(fd) == -1)
    {
        perror("close fd 1");
        return -1;
    }

    //重新打开文件
    if((fd = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }

    printf("open success fd = %d\n", fd);     //3

    Stu temp;        //要接受数据的容器
    read(fd, &temp, sizeof(temp));

    printf("姓名:%s, 年龄:%d, 成绩:%.2lf\n", temp.name, temp.age, temp.score);

    //关闭文件
    close(fd);

    return 0;
}
3.5lseek光标偏移
       #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);
    功能:移动文件的光标
    参数1:文件描述符
    参数2:偏移量
            >0:向后偏移
            =0:不偏移
            <0:向前偏移
    参数3:偏移起始位置
            SEEK_SET:文件开头
            SEEK_END:文件结尾
            SEEK_CUR:文件当前位置
    返回值:成功返回文件光标当前的位置,失败返回-1并置位错误码

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //打开文件,以读写的形式
    int fd = -1;
    if((fd = open("./gg.bmp", O_RDWR)) == -1)
    {
        perror("open error");
        return -1;
    }

    //偏移光标
    lseek(fd, 2, SEEK_SET);

    //定义变量接受大小
    int img_size = 0;
    read(fd, &img_size, sizeof(img_size));
    printf("img_size = %d\n", img_size);

    //将光标直接偏移到文件末尾,返回值就是文件大小
    printf("size = %ld\n", lseek(fd, 0, SEEK_END));

    //关闭文件
    close(fd);

    return 0;
}
3.6文件描述符拷贝问题

1> 简单完成两个文件描述符变量的拷贝

这种情况下,没有新文件描述符产生,使用的是同一个文件描述符,共享同一个文件光标

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件描述符变量
    int fd1 = -1;
    //打开文件
    if((fd1 = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }
    
    //定义变量存储文件描述符
    int fd2 = fd1;

    //通过fd2完成文件光标的偏移
    lseek(fd2, 8, SEEK_SET);

    //从fd1中读取数据、
    char buf[128] = "";
    read(fd1, buf, 5);
    printf("buf = %s\n", buf);          //nihao:说明fd1和fd2共用同一个光标
                            //hello:说明不共用光标

    //关闭文件描述符
    close(fd1);

    return 0;
}

2> dup函数完成拷贝

该操作,会生成新的文件描述符,但是与旧的文件描述符共享同一个光标

    #include <unistd.h>

       int dup(int oldfd);
    功能:拷贝旧文件描述符,生成新的文件描述符
    参数:旧文件描述符
    返回值:新文件描述符

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件描述符变量
    int fd1 = -1;
    //打开文件
    if((fd1 = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }
    
    //定义变量存储文件描述符
    int fd2 = dup(fd1);

    printf("fd1 = %d, fd2 = %d\n", fd1, fd2);  //3   4

    //通过fd2完成文件光标的偏移
    lseek(fd2, 8, SEEK_SET);

    //从fd1中读取数据、
    char buf[128] = "";
    read(fd1, buf, 5);
    printf("buf = %s\n", buf);          //nihao:说明fd1和fd2共用同一个光标
                            //hello:说明不共用光标

    //关闭文件描述符
    close(fd1);

    return 0;
}

3> 使用dup2拷贝文件描述符

 int dup2(int oldfd, int newfd);
    功能:拷贝旧文件描述符,放入新文件描述符中,如果新文件描述符之前已经打开,则在拷贝时,默认将其关闭
    参数1:旧文件描述符
    参数2:新文件描述符
    返回值:成功返回新文件描述符,失败返回-1并置位错误码

#include<myhead.h>

int main(int argc, const char *argv[])
{

    //打开一个文件
    int fd2 = -1;
    if((fd2 = open("./tt.c", O_RDONLY))==-1)
    {
        perror("open error");
        return -1;
    }
    printf("fd2 = %d\n", fd2);         //3


    //定义文件描述符变量
    int fd1 = -1;
    //打开文件
    if((fd1 = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }
    
    //定义变量存储文件描述符
    dup2(fd1 ,fd2);

    printf("fd1 = %d, fd2 = %d\n", fd1, fd2);  //4    3

    //通过fd2完成文件光标的偏移
    lseek(fd2, 8, SEEK_SET);

    //从fd1中读取数据、
    char buf[128] = "";
    read(fd1, buf, 5);
    printf("buf = %s\n", buf);          //nihao:说明fd1和fd2共用同一个光标
                                    //hello:说明不共用光标

    //关闭文件描述符
    close(fd1);

    return 0;
}

4> dup2常用用途

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件描述符
    int fd = -1;
    if((fd = open("./aa.txt", O_WRONLY|O_CREAT|O_TRUNC, 0664)) == -1)
    {
        perror("open error");
        return -1;
    }

    //将标准输出拷贝到fd中
    dup2(fd, STDOUT_FILENO);       //将标准输出重定向到文件中
    dup2(fd, STDIN_FILENO);        //将标准输入重定向到文件中
    dup2(fd, STDERR_FILENO);       //将标准出差重定向到文件中

    printf("hello a\n");        //?
    printf("hello a\n");        //?
    printf("hello a\n");        //?
    printf("hello a\n");        //?
    printf("hello a\n");        //?



    //关闭文件
    close(fd);

    return 0;
}

5> 多次使用open函数打开同一个文件时,这多个文件描述符是不共享文件光标的

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //定义文件描述符
    int fd1 = -1;
    if((fd1 = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }

    //定义文件描述符
    int fd2 = -1;
    if((fd2 = open("./file.txt", O_RDONLY)) == -1)
    {
        perror("open error");
        return -1;
    }

    //移动fd1的光标
    lseek(fd1, 8, SEEK_SET);

    //从fd2中读取数据
    char buf[10] = "";
    read(fd2, buf, 5);

    printf("buf = %s\n", buf);        //?


    //关闭文件
    close(fd1);
    close(fd2);

    return 0;
}

四.文件属性函数

1> 函数原型

       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *pathname, struct stat *statbuf);
       功能:获取给定的文件状态属性
       参数1:要获取的文件名
       参数2:文件属性结构体指针,是一个地址传递,需要传递一个结构体变量的地址,通过函数调用结束后,该变量中就有内容了
       struct stat {
               dev_t     st_dev;         /* 设备号 */
               ino_t     st_ino;         /* Inode 号 */
               mode_t    st_mode;        /* 文件类型和文件权限 */
               nlink_t   st_nlink;       /* 硬链接数 */
               uid_t     st_uid;         /* 拥有者的用户id号 */
               gid_t     st_gid;         /* 拥有者的组id号 */
               dev_t     st_rdev;        /* 特殊文件的设备号 */
               off_t     st_size;        /* 总大小,以字节为单位 */
               blksize_t st_blksize;     /* 块的大小 */
               blkcnt_t  st_blocks;      /* 总块数 */

             
           };
        如何获取文件的类型和文件权限
        1>    使用st_mode & S_IFMT可以得到文件的类型
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
        2>    使用st_mode & 0777可以得到文件的权限
           S_ISUID     04000   set-user-ID bit
           S_ISGID     02000   set-group-ID bit (see below)
           S_ISVTX     01000   sticky bit (see below)

           S_IRWXU     00700   owner has read, write, and execute permission
           S_IRUSR     00400   owner has read permission
           S_IWUSR     00200   owner has write permission
           S_IXUSR     00100   owner has execute permission

           S_IRWXG     00070   group has read, write, and execute permission
           S_IRGRP     00040   group has read permission
           S_IWGRP     00020   group has write permission
           S_IXGRP     00010   group has execute permission

           S_IRWXO     00007   others (not in group) have read,  write,  and
                               execute permission
           S_IROTH     00004   others have read permission
           S_IWOTH     00002   others have write permission
           S_IXOTH     00001   others have execute permission
       
       返回值:成功返回0,失败返回-1并置位错误码


#include<myhead.h>

int main(int argc, const char *argv[])
{
    //判断外部传来的文件
    if(argc != 2)
    {
        printf("input file error\n");
        return -1;
    }

    //定义接受文件的属性结构体变量
    struct stat sb;                 //stat buf
    //调用函数,获取文件状态
    if(stat(argv[1], &sb) == -1)
    {
        perror("stat error");
        return -1;
    }

    //程序执行至此,sb中就记录了传入的文件的信息
    //输出文件类型
    switch(sb.st_mode & S_IFMT)
    {
    case S_IFSOCK:
        {
            printf("套接字文件\t");
        }
        break;
    case S_IFLNK:
        {
            printf("链接文件\t");
        }
        break;
    case S_IFREG:
        {
            printf("普通文件\t");
        }
        break;
    case S_IFBLK:
        {
            printf("块设备文件\t");
        }
        break;
    case S_IFDIR:
        {
            printf("目录文件\t");
        }
        break;
    case S_IFCHR:
        {
            printf("字符设备文件\t");
        }
        break;
    case S_IFIFO:
        {
            printf("管道文件\t");
        }
        break;
    }

    //输出文件权限
    printf("%#o\t", sb.st_mode&0777);
    //输出文件大小
    printf("%ld\t", sb.st_size);
    //输出文件inode号
    printf("%ld\n", sb.st_ino);

    return 0;
}

 作业

使用文件IO完成,将源文件中的所有内容进行加密(大写转小写、小写转大写)后写入目标文件中

源文件内容不变

#include <myhead.h>

int main(int argc, const char *argv[])
{
	if(argc!=3)//判断传入的文件是否等于三
	{
		perror("file input error");
		return -1;
	}
	int fp=-1;
	if((fp=open(argv[1],O_RDONLY))==-1)//以只读的形式打开要加密文件,并判断是否打开成功
	{
		perror("argv[1] open error");
		return -1;
	}
	int fd=-1;
	if((fd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664))==-1)//以只写的形式打开加密后文件,并判断是否打开成功
	{
		perror("argv[2] open error");
		return -1;
	}
	char flag=0;//定义存储容器
	while(0!=read(fp,&flag,sizeof(flag)))//在要加密文件中读取一个字附直到全部读取结束
	{
		if(flag>='a'&&flag<='z')//判断是不是字母,是字母开始加密
		{
			flag=flag-32;
		}
		else if(flag>='A'&&flag<='Z')
		{
			flag=flag+32;
		}
		write(fd,&flag,sizeof(flag));//将加密后字符写入文件
	}
	printf("加密成功!\n");
	close(fp);//关闭文件
	close(fd);
	return 0;
}
  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值