文件IO(1)--creat和open

    今天开始学习unix/linux系统下的文件I/O函数—打开文件、读文件、写文件等。大多数文件I/O只需要用到5个函数:open,read,write,lseek已经close,这5个函数都直接调用同名的系统调用,所以是不带缓冲的,本节,主要介绍open和creat函数。

 

1.open函数

1)函数原型:

#include <fcntl.h>

int open(const char* pathname,int flags)

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

 

2)函数功能:

打开或建立一个文件。对于open函数,仅当创建文件时,才用到第三个参数

 

3)参数说明:

pathname:打开或创建的文件名

 

flags:用下列一个或多个常量进行“或”运算构成flags参数(这些常量定义在<fcntl.h>

O_RDONLY   只读打开

O_WRONLY   只写打开

O_RDWR     读写打开

以上三个常量只能选一个,下面的则可以多选:

O_APPEND   每次写时都追加到文件的尾端。

O_CREAT     若此文件不存在,则创建它。使用此选项时,需要第三个参数mode,用其     

              指定新文件的访问权限。

O_EXCL      如果同时制定了O_CREAT,而文件已经存在,则会报错。因此可以测试一个

              文件是否存在,如果不存在,则创建此文件,这使测试和创建两者成为一个

              原子操作。

O_TRUNC     如果此文件存在,而且为只读或读写成功打开,则将其长度截短为0。

O_NOCTTY    如果pathname指的是终端设备,则不将该设备分配作为此进程的控制终端。

O_NONBLOCK 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,

               则此选项为文件的本次打开操作和后续的I/O操作设置非阻塞模式。

 

mode:用下列一个或多个常量进行“或”运算构成mode参数(这些常量定义在sys/stat.h)

S_IRWXU:00700 拥有者读写执行权限

S_IRUSR: 00400 拥有者读权限

S_IWUSR:00200  拥有者写权限

S_IXUSR: 00100 拥有者执行权限

S_IRWXG:00070 组内成员读写执行权限

S_IRGRP: 00040 组内成员读权限

S_IWGRP:00020  组内成员写权限

S_IXGRP: 00010 组内成员执行权限

S_IRWXO:00007 其他成员读写执行权限

S_IROTH: 00004 其他成员读权限

S_IWOTH:00002  其他成员写权限

S_IXOTH: 00001 其他成员执行权限

 

也可以直接指定mode的值,如0777,0541等

注意:此处设定的mode的值并不是文件最终的权限,文件最终的权限是按照mode & ~umask得到的,而默认的umask是0022,所以如果想按照mode的值设置文件权限,需要在建立文件之前将umask的值设置为0000

 

4)实例程序:

以下程序当不存在test.txt时创建一个test.txt文件,并给予最大权限

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

#include <errno.h>

 

int main()

{

       int fd;

       umask(0000);

       //if((fd = open("test.txt",O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,0777)) == -1)

       if((fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,S_IRWXU |  

               S_IRWXG | S_IRWXO)) == -1)

       {

              //printf("open:%s with errno:%d\n",strerror(errno),errno);         perror("open");

              perror(“open”);

              exit(1);

       }

       else

       {

              printf("success");

       }

 

       close(fd);

       return 0;

}

 

 

执行结果:

[hb@localhost unixadvance]$ gcc -g -o testOpen testOpen.c

[hb@localhost unixadvance]$ ./testOpen

success

[hb@localhost unixadvance]$ ls -al

总计 76

drwxrwxr-x 2 hb   hb    4096 08-02 11:19 .

drwxrwxrwx 5 root root  4096 08-01 23:49 ..

-rwxrwxr-x 1 hb   hb    5476 08-02 11:17 a.out

-rw-rw-r-- 1 hb   hb     529 08-02 11:03 testCreat.c

-rwxrwxr-x 1 hb   hb    6696 08-02 11:19 testOpen

-rw-rw-r-- 1 hb   hb     529 08-02 11:17 testOpen.c

-rw-r--r-- 1 root root 12288 08-02 11:17 .testOpen.c.swp

-rwxrwxrwx 1 hb   hb       0 08-02 11:19 test.txt

     

可以看到test.txt的权限确实是777,而如果去掉程序中umask(0000)一句,则创建出来的文件权限为:

[root@localhost unixadvance]# ls -al

总计 76

drwxrwxr-x 2 hb   hb    4096 08-02 11:25 .

drwxrwxrwx 5 root root  4096 08-01 23:49 ..

-rwxrwxr-x 1 hb   hb    5476 08-02 11:17 a.out

-rw-rw-r-- 1 hb   hb     529 08-02 11:03 testCreat.c

-rwxr-xr-x 1 root root  6595 08-02 11:25 testOpen

-rw-rw-r-- 1 hb   hb     531 08-02 11:21 testOpen.c

-rw-r--r-- 1 root root 12288 08-02 11:21 .testOpen.c.swp

-rwxr-xr-x 1 root root     0 08-02 11:25 test.txt

这是因为默认的umask是022,所以默认的文件权限就为0755。

 

当我们第二次执行此程序:

[root@localhost unixadvance]# ./testOpen

open: File exists

 

File exists这个错误是由perror("open")报出来的,它定义在<stdio.h>中

perror (const char *s)用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 设备 (stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno 的值来决定要输出的字符串。

   在库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和现在的errno所对应的错误一起输出。

     如果想看到errno的值,则将perror()替换为

printf("open:%s with errno:%d\n",strerror(errno),errno);           perror("open");

此时的执行结果为:

[root@localhost unixadvance]# ./testOpen

open:File exists with errno:17

 

errno定义在<errno.h>中

 

2.creat函数

1)函数原型:

#include <fcntl.h>

int creat(const char *pathname ,mode_t  mode);

 

2)函数功能:

创建一个新文件。

creat函数等效于如下函数:

open(pathname,O_WRONLY | O_CREAT | O_TRUNC, mode)

注意:creat只能以只写方式打开,不能读,读出的将是乱码!

 

3)参数说明:

pathname:创建的文件名

mode:与open的mode相同

 

4)程序实例:

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

#include <errno.h>

 

int main()

{

       int fd;

       umask(0000);

       if((fd = creat("test.txt",0777)) == -1)

       {

              //perror("open");

              printf("open:%s with errno:%d\n",strerror(errno),errno);

              exit(1);

       }

       else

       {

              printf("success\n");

       }

 

       close(fd);

       return 0;

 

}

 

运行结果:

[root@localhost unixadvance]# gcc testCreat.c

[root@localhost unixadvance]# ./a.out

success

[root@localhost unixadvance]# ls -al

总计 76

drwxrwxr-x 2 hb   hb    4096 08-02 15:02 .

drwxrwxrwx 5 root root  4096 08-01 23:49 ..

-rwxr-xr-x 1 root root  5462 08-02 15:02 a.out

-rw-rw-r-- 1 hb   hb     529 08-02 15:02 testCreat.c

-rw-r--r-- 1 root root 12288 08-02 15:02 .testCreat.c.swp

-rwxr-xr-x 1 root root  6907 08-02 11:39 testOpen

-rw-rw-r-- 1 hb   hb     611 08-02 11:39 testOpen.c

-rwxrwxrwx 1 root root     0 08-02 15:02 test.txt

 

当我们第二次运行程序:

[root@localhost unixadvance]# ./a.out

success

 

仍然是success,说明creat函数不管原来有没有同名文件都会返回成功,那是否覆盖了呢?我们继续试验:

在已经生成的test.txt里加入一句话:This is the old one!

 

然后将原程序中fd = creat("test.txt",0777) 改为 fd = creat("test.txt",0700),结果如下:

[root@localhost unixadvance]# ./a.out

success

[root@localhost unixadvance]# ls -al

总计 76

drwxrwxr-x 2 hb   hb    4096 08-02 15:08 .

drwxrwxrwx 5 root root  4096 08-01 23:49 ..

-rwxr-xr-x 1 root root  5462 08-02 15:08 a.out

-rw-rw-r-- 1 hb   hb     530 08-02 15:08 testCreat.c

-rw-r--r-- 1 root root 12288 08-02 15:08 .testCreat.c.swp

-rwxr-xr-x 1 root root  6907 08-02 11:39 testOpen

-rw-rw-r-- 1 hb   hb     611 08-02 11:39 testOpen.c

-rwxrwxrwx 1 root root     0 08-02 15:08 test.txt

 

说明:如果创建的文件与现有文件重名,则creat函数会将重名文件内容清零(这其实是由O_TRUNC标志位决定的),但原文件的权限却不会被改变!!

posted on 2012-08-02 15:55  好坏  阅读(8621)  评论(0编辑  收藏  举报

导航