文件的創建和讀寫
當我們需要打開一個文件進行讀寫操作的時候,我們可以使用系統調用函數open。使用完成以后我們調用另外一個close函數進行關閉操作。
該函數使用的頭文件如下:
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
定義函數:
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
int close(int fd);
函數說明:
open函數有兩個形式。其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認為在當前路徑下面)。flags可以取下面的一個值或者是幾個值的組合。?
O_RDONLY:以只讀的方式打開文件。?
O_WRONLY:以只寫的方式打開文件。
O_RDWR:以讀寫的方式打開文件。?
O_APPEND:以追加的方式打開文件。?
O_CREAT:創建一個文件。
O_EXEC:如果使用了O_CREAT而且文件已經存在,就會發生一個錯誤。
O_NOBLOCK:以非阻塞的方式打開一個文件。
O_TRUNC:如果文件已經存在,則刪除文件的內容。?
前面三個標志只能使用任意的一個。如果使用了O_CREATE標志,那么我們要使用open的第二種形式。還要指定mode標志,用來表示文件的訪問權限。mode可以是以下情況的組合。?
-----------------------------------------------------------------
S_IRUSR 用戶可以讀 S_IWUSR 用戶可以寫?
S_IXUSR 用戶可以執行 S_IRWXU 用戶可以讀寫執行
-----------------------------------------------------------------
S_IRGRP 組可以讀 S_IWGRP 組可以寫?
S_IXGRP 組可以執行 S_IRWXG 組可以讀寫執行
-----------------------------------------------------------------
S_IROTH 其他人可以讀 S_IWOTH 其他人可以寫?
S_IXOTH 其他人可以執行 S_IRWXO 其他人可以讀寫執行
-----------------------------------------------------------------
S_ISUID 設置用戶執行ID S_ISGID 設置組的執行ID?
-----------------------------------------------------------------
????我們也可以用數字來代表各個位的標志。Linux總共用5個數字來表示文件的各種權限。?
00000第一位表示設置用戶ID,第二位表示設置組ID,第三位表示用戶自己的權限位,第四位表示組的權限,最后一位表示其他人的權限。?每個數字可以取1(執行權限),2(寫權限),4(讀權限),0(什么也沒有)或者是這幾個值的和。比如我們要創建一個用戶讀寫執行,組沒有權限,其他人讀執行的文件。
設置用戶ID位可以使用的模式是:
1.(設置用戶ID)0(組沒有設置)7(1+2+4)0(沒有權限,使用缺省) 5(1+4)?即10705
open("temp",O_CREAT,10705);
????如果我們打開文件成功,open會返回一個文件描述符。對文件的所有操作就可以對這個文件描述符進行操作。
????當我們操作完成以后,我們要關閉文件了,只要調用close就可以了,其中fd是我們要關閉的文件描述符。
????文件打開了以后,就可以對文件進行讀寫了。可以調用函數read和write進行文件的讀寫。
該函數使用的頭文件:
#include <unistd.h>
函數定義:
ssize_t read(int fd, void *buffer,size_t count);
ssize_t write(int fd, const void *buffer,size_t count);
函數說明:
????fd是我們要進行讀寫操作的文件描述符,buffer是我們要寫入文件內容或讀出文件內容的內存地址,count是我們要讀寫的字節數。對于普通的文件read從指定的文件(fd)中讀取count字節到buffer緩沖區中(記住我們必須提供一個足夠大的緩沖區),同時返回count,如果read讀到了文件的結尾或者被一個信號所中斷,返回值會小于count。如果是由信號中斷引起返回,而且沒有返回數據,read會返回-1,且設置errno為EINTR。當程序讀到了文件結尾的時候,read會返回0。?
?????write從buffer中寫count字節到文件fd中,成功時返回實際所寫的字節數。?
2.文件的各個屬性
????文件具有各種各樣的屬性,除了我們上面所知道的文件權限以外,文件還有創建時間、大小等等屬性,有時侯我們要判斷文件是否可以進行某種操作(讀,寫等等)。這個時候我們可以使用access函數。
#include <unistd.h>
int access(const char *pathname,int mode);
pathname:是文件名稱,mode是我們要判斷的屬性。可以取以下值或者是他們的組合。?
R_OK文件可以讀
W_OK文件可以寫
X_OK文件可以執行
F_OK文件存在
????當我們測試成功時,函數返回0,否則如果有一個條件不符時,返回-1。如果我們要獲得文件的其他屬性,我們可以使用函數stat或者fstat。
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name,struct stat *buf);
int fstat(int filedes,struct stat *buf);
struct stat {
dev_t st_dev; ?/* 設備 */
ino_t st_ino; /* 節點 */
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_off; ? /* 文件字節數 */
unsigned long st_blksize; /* 塊大小 */
unsigned long st_blocks; ?/* 塊數 */
time_t st_atime; ?/* 最后一次訪問時間 */
time_t st_mtime; ?/* 最后一次修改時間 */
time_t st_ctime; ?/* 最后一次改變時間(指屬性) */
};
Stat用來判斷沒有打開的文件,而fstat用來判斷打開的文件。我們使用最多的屬性是st_ mode。通過著屬性我們可以判斷給定的文件是一個普通文件還是一個目錄,連接等等。可以使用下面幾個宏來判斷:
S_ISLNK(st_mode)是否是一個連接,S_ISREG是否是一個常規文件,S_ISDIR是否是一個目錄,S_ISCHR是否是一個字符設備,S_ISBLK是否是一個塊設備,S_ISFIFO是否是一個FIFO文件,S_ISSOCK是否是一個SOCKET文件。
目錄文件的操作:
????在我們編寫程序的時候,有時候會要得到我們當前的工作路徑。C庫函數提供了getcwd來解決這個問題。
#include <unistd.h>
char *getcwd(char *buffer,size_t size);
????我們提供一個size大小的buffer,getcwd會把我們當前的路徑考到buffer中。如果buffer 太小,函數會返回-1和一個錯誤號。?
Linux提供了大量的目錄操作函數,我們學習幾個比較簡單和常用的函數。?
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char *path,mode_t mode);
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dir);
void rewinddir(DIR *dir);
off_t telldir(DIR *dir);
void seekdir(DIR *dir,off_t off);
int closedir(DIR *dir);
struct dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[NAME_MAX+1]; /* 文件名稱 */
mkdir創建一個目錄,opendir打開一個目錄為以后讀做準備,readdir讀一個打開的目錄,rewinddir是用來重讀目錄,closedir是關閉一個目錄,telldir和seekdir類似與ftee和fseek函數。