• 第三季-第8课-系统调用方式文件编程


    第8课-系统调用方式文件编程

     

    8.1核心理论-文件描述符

    在中国,每一个成年的公民都会有一个身份证编号,它的本质就是一个数字,我们可以利用这个数字来标记这个公民。在Linux系统中,所有打开的文件也对应一个数字,这个数字由系统来分配,我们称之为:文件描述符。

    8.2 函数学习

    用man+文件名的方式查看函数的用法。

    1.打开文件

    (1)函数名

    open

    (2)函数原形

    int open(const char *pathname,int flags);

    int open(const char *pathname,int flags,mode_t mode);

    (3)函数功能

    打开或者创建一个文件

    (4)所属头文件

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcbtl.h>

    (5)返回值

    成功:文件描述符;失败:-1.

    (6)参数说明

    pathname:要打开的文件名(含路径)

    flags:文件打开的标志,它只能使用O_RDONLY,O_WDONLY,O_RDWR中的一个。

    -O_APPEND:已追加的方式打开文件

    -O_CREAT:当文件不存在的时候,创建这个文件

    mode:一定是在flags中使用了O_CREAT标志,mode记录待创建文件的访问权限。

    (7)测试文件

    不用新创建文件的:

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    void main()

    {

             int fd;

             fd = open("/home/text.c",O_RDWR);

             if(fd<0)

                       printf("open file fail! ");

    }

    该文件在编译的时候会出,printf不相容的警报,忽略即可。

    新创建文件的:

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    void main()

    {

             int fd;

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                      printf("open file fail! ");

    }

    1. 创造文件

    (1)函数名

    creat

    (2)函数原形

    int creat(const char *pathname,mode_t mode)

    (3)函数功能

    创建一个文件,并且以只写的方式打开该文件。

    (4)所属头文件

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    (5)返回值

    成功:文件描述符

    失败:-1

    (6)参数说明

    pathname:要打开的文件名(含路径)

    mode:创建文件的读写权限

    (7)示例程序

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    void main()

    {

             int fd;

             fd = creat("/home/test2.c",0621);

             if(fd<0)

                       printf("fail ");

    }

    1. 关闭文件

    (1) 函数名

    close

    (2)函数原形

    int close(int fd)

    (3) 函数功能

    关闭一个打开的文件。

    (4) 所属头文件

    #include<unistd.h>

    (5) 返回值

    成功:0

    失败:-1

    (6)参数说明

    fd:待关闭的文件描述符

    (8)示例程序

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

             int fd;

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                       printf("open file fail! ");

             close(fd);

    }

    1. 读文件

    这里需要注意,我们使用man read命令的时候会发生错误,找的不是我们要找的文件。我们需要了解man命令是相当于一个菜单的,只要包含几个方面的章节(1)命令;(2)系统调用函数;(3)库函数。

    当使用man read时,关键字是read。它会默认的从第一个章节里面找,若果第一个章节里面找不到才会在下面的章节里面找。可是,在第一个章节里面是有read这个关键字的,所以我们查到的不是我们要的那个属于系统调用函数的关键字。我们使用man 2 read查找就好。

    (1) 函数名

    read

    (2)函数原形

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

    (3)函数功能

    从一个打开的文件中读取数据

    (4)所属头文件

    #include<unistd.h>

    (5)返回值

    成功:返回读取的字节数

    失败:-1

    (6)参数说明

    fd:打开的文件描述符(要读取的数据的文件描述符)

    count:希望读取的字节数

    buf:指向读取来的数据存到buf指向非空间

    (7)范例程序

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

             int fd;

             char buf[10];

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                       printf("open file fail! ");

             read(fd,buf,5);

             buf[5] = "";

             printf("buf is %s ",buf);

             close(fd);

    }

    1. 写文件

    (1) 函数名

    write

    (2)函数原形

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

    (3)函数功能

    向一个打开的文件中写入数据

    (4)所属头文件

    #include<unistd.h>

    (5)返回值

    成功:返回写入到文件里面的字节数

    失败:-1

    (6)参数说明

    fd:写入的文件描述符(要写入的数据的文件描述符)

    count:希望写入的字节数

    buf:buf指向非空间的数据写入到文件

    (8)范例程序

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

             int fd;

             char *buf = "987654321";

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                       printf("open file fail! ");

             write(fd,buf,10);

             printf("buf is %s ",buf);

             close(fd);

    }

    1. 定位文件

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

             int fd;

             char *buf = "987654321";

             char buf1[10];

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                       printf("open file fail! ");

             write(fd,buf,7);

             read(fd,buf1,5);

             buf1[5] = "";

    printf("buf1 is %s ",buf1);

             close(fd);

    }

    我们首先看到这个测试程序,按道理来分析,我们存入7个字节,读取5个字节,应该是不冲突额,应该能读出来98765这几个字节。但是,在操作的过程中,我们却读出来了空的内容。原因是我们在执行文件的时候,比如write函数写入7个字节,那么它的指针也是指向第七个字节后面。当执行read操作时,我们从指针的位置开始执行,自然什么也没有是空的。怎么解决这一个问题呢?我们下面介绍

    (1) 函数名

    lseek

    (2)函数原形

    off_t lseek(int fd,off_t offset,int whence);

    (3)函数功能

    重新定位文件的读写位置

    (4)所属头文件

    #include<unistd.h>

    #include<sys/types.h>

    (5)返回值

    成功:返回移动后的文件指针距离文件头的位置

    失败:-1

    (6)参数说明

    fd:文件描述符(指定的使我们要操作的文件)

    whence:表示指针的开始位置,只能取下面的三种值。

    SEEK_SET文件的开头加上offset(正的)

    SEEK_CUR当前的指针加上offset(可正可负)的位置

    SEEK_END从文件的末尾加上offset(负的)

    offset:指针将要加的数。

    (7)范例程序

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

             int fd;

             char *buf = "1234567890";

             char buf1[10];

             fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

             if(fd<0)

                       printf("open file fail! ");

             write(fd,buf,10);

             lseek(fd,0,SEEK_SET);

             read(fd,buf1,5);

             buf1[5] = "";

             printf("buf1 is %s ",buf1);

             close(fd);

    }

    1. 复制文件描述符

    (1) 函数名

    dup

    (2)函数原形

    int dup(int oldfd);

    (3)函数功能

    复制一个文件描述符

    (4)所属头文件

    #include<unistd.h>

    (5)返回值

    成功:返回新的文件描述符

    失败:-1

    (6)参数说明

    oldfd:待复制的文件描述符

    (7)范例程序

            #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main()

    {

            int fd;

            int fd1;

            char *buf = "1234567890";

            char buf1[10];

            fd = open("/home/text1.c",O_RDWR|O_CREAT,0755);

            if(fd<0)

             printf("open file fail! ");

            fd1 = dup(fd);

            write(fd1,buf,10);

            lseek(fd1,0,SEEK_SET);

            read(fd1,buf1,5);

            buf1[5] = "";

            printf("buf1 is %s ",buf1);

            close(fd1);

    }

    8.3综合实例

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<unistd.h>

    void main(int argc,char **argv)

    {

             int fd_s;

             char buf[512];

             int count = 0;

             int fd_t;

    //1.打开原文件

    fd_s = open(argv[1],O_RDONLY);

    //2.打开目标文件

             fd_t = open(argv[2],O_RDWR|O_CREAT,0666);

    //3.读取原文件中的数据,将读取出的原文件数据写入目标文件

             while((count = read(fd_s,buf,512))>0)

                                write(fd_t,buf,512);

    //4.关闭文件

             close(fd_s);

             close(fd_t);

    }       

            当我们使用上面编辑的代码,运行./filecp t.txt s.txt时,我们会发现生成的s.txt中有许多的乱码,原因是,我们每一次都是进行512个字节的复制,当不满足512个字节的时候,我们仍然按照512个字节去复制,于是出现了问题。我们将文件进行如下的修改:

             while((count = read(fd_s,buf,512))>0)

                       write(fd_t,buf,count);

             这样我们的./filecp就可以当做cp命令来使用。

  • 相关阅读:
    Mysql 创建外键 1005 err 150
    骑车目标
    windows 如何查看端口占用进程ID 进程名称 强制结束进程
    Eclipse去除JavaScript验证错误
    MyEclipse 代码里的中文字太小设置方法
    security自动登陆
    Tomcat 7 可以修改 Session 默认的 Cookie 名 JSESSIONID 了
    windows2008 安装oracle10g“程序异常终止。发生内部错误。请将以下文件提供给oracle技术支持部门
    ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段(EXP-00056: 遇到 ORACLE 错误 1652 ORA-01652: unable to extend temp segment by 128 in tablespace TEMP)
    oracle数据库启动时出现ORA-01157和ORA-01110问题
  • 原文地址:https://www.cnblogs.com/free-1122/p/11342227.html
Copyright © 2020-2023  润新知