文件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標志位決定的),但原文件的權限卻不會被改變!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM