第三季-第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命令来使用。

原文地址:https://www.cnblogs.com/free-1122/p/11342227.html