我們都知道linux下所有設備都是以文件存在的,所以當我們需要用到這些設備的時候,首先就需要打開它們,下麵我們來詳細瞭解一下文件I/O操作。 用到的文件I/O有以下幾個操作:打開文件、讀文件、寫文件、關閉文件等,對應用到的函數有:open、read、write、close、lseek(文件指針偏移) ...
我們都知道linux下所有設備都是以文件存在的,所以當我們需要用到這些設備的時候,首先就需要打開它們,下麵我們來詳細瞭解一下文件I/O操作。
用到的文件I/O有以下幾個操作:打開文件、讀文件、寫文件、關閉文件等,對應用到的函數有:open、read、write、close、lseek(文件指針偏移)
文件描述符:對於內核而言,所有打開的文件都通過文件按描述符引用。文件描述符是一個非負整數。
當打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符。
當讀、寫一個文件時,使用open/creat返回的文件描述符標識該文件,將其作為參數傳送給read或write。
linux系統下文件描述符0是標準輸入,1是標準輸出,2是標準出錯,所以一般打開文件的時候文件描述符都是從3開始。 這裡read和write是不能格式化讀取和寫入,如果想瞭解文件怎麼格式化讀取和寫入的話,可以看看我以前寫的一篇隨筆。
一、打開文件 (1)頭文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> (2)函數原型 int open(const char *pathname, int flags); 參數: a、pathname:打開或者創建的文件名字,如"text" b、 flags: O_RDONLY:只讀打開 O_WRONLY:只寫打開 O_RDWR:讀、寫打開 O_CREAT:若此文件不存在則創建它,使用O_CREAT時後面要跟文件的訪問許可權位,如O_CREAT,0777 O_APPEND:每次寫時都追加到文件的尾端 O_EXCL :如果同時指定了O_CREAT,而文件已經存在,則出錯,用此可以測試一個文件是否 存在,如果不存在,則創建此文件,這使測試和創建兩者成為一個原子操作 O_DSYNC:使每次write等待物理I/O操作完成,但是如果該寫操作並不影響讀取剛寫入的 數據,則不需等待文件屬性被更新 O_NONBLOCK :如果path引用的是一個FIFO、一個塊特殊文件或一個字元特殊文件,則 此選項為文件的本次打開操作和後續的I/O操作設置非阻塞方式 O_NOCTTY:如果path引用的是 終端設備,則將該設備分配為此進程的控制終端 O_SYNC:使每次write要等待物理I/O操作完成,包括有該write引起的文件屬性更新所需的I/O O_TRUNC:如果文件存在,並且是常規文件而且以讀寫或者只寫打開,則將其長度截斷為0, 如果文件是FIFO或終端設備文件,O_TRUNC標誌被忽略,否則O_TRUNC不明確 O_DIRECTORY:如果pathname引用的不是目錄,則出錯 (3)返回值: 成功:文件描述符 失敗:-1 二、讀取文件 (1)頭文件 #include <unistd.h> (2)函數原型 ssize_t read(int fd, void *buf, size_t count); 參數: a、fd:調用open後返回的文件描述符 b、buf:用來存放從文件中讀到的數據的緩衝區 c、count:讀取的位元組數 (3)返回值: 成功:讀到的位元組數,如果讀到文件尾端,則返回0 失敗:-1 三、寫數據 (1)頭文件 #include <unistd.h> (2)函數原型 ssize_t write(int fd, const void *buf, size_t count); 參數: a、fd:調用open後返回的文件描述符 b、buf:從來存放數據的緩衝區 c、count:寫入數據的位元組數 (3)返回值: 成功:返回已寫的位元組數 失敗:-1 四、關閉文件 (1)頭文件 #include <unistd.h> (2)函數原型 int close(int fd); 參數: a、fd:調用open後返回的文件描述符 五、文件偏移 (1)頭文件 #include <sys/types.h> #include <unistd.h> (2)函數原型 off_t lseek(int fd, off_t offset, int whence); 參數: a、fd:調用open後返回的文件描述符 b、offset 和參數whence有關,通常設置為0 (according to thedirective whence as follows) c、whence: SEEK_SET: 將文件的偏移量設置為距文件開始處offset個位元組 SEEK_CUR:將文件的偏移量設置為其當前值加offset個位元組,offset可為正或負 SEEK_END: 將文件的偏移量設置為文件長度加offset,offset可為正或負 (3)返回值: 成功:返回新的文件偏移量 失敗:-1
下麵是代碼:
#include <sys/types.h> #include <sys/stat.h> #include <sys/fcntl.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define PATHNAME "text.txt" #define LENGTH 4096 void error(char *name) //錯誤提示 { perror(name); exit(1); } int main(int argc,char *argv[]) { int fd ; //存放文件描述符 int size1; //讀操作時的返回值 int size; //寫操作時的返回值 int offset; //文件偏移量 //打開文件 /*O_REWR表示已讀寫許可權打開文件,O_CREAT表示如果文件不存在則創建 *創建的新文件的許可權為0777,即是可讀可寫可執行,O_APPEND表示 *寫入數據時從文件尾端寫入*/ if((fd = open(PATHNAME,O_RDWR|O_CREAT|O_APPEND,0777)) == -1) { error("open"); } char buf[LENGTH]; bzero(buf,sizeof(buf)); //從文件中讀取數據 if((size1 = read(fd,buf,sizeof(buf))) == -1) { error("read"); } printf("%s\n",buf); char buf1[LENGTH] = "小世界"; //寫入數據到文件中 if((size = write(fd,buf1,sizeof(buf))) == -1) { error("write"); } char buf3[LENGTH] = "hello world"; if((size = write(fd,buf3,sizeof(buf3))) == -1) { error("write"); } //因為寫入數據到文件中的時候已經把文件指針偏移到文件尾端了,所以要重新把文件指針偏移到文件頭,方便下麵的讀操作 if((offset = lseek(fd,0,SEEK_SET)) == -1) { error("lseek"); } bzero(buf,sizeof(buf)); if((size1 = read(fd,buf,sizeof(buf))) == -1) { error("read"); } printf("%s\n",buf); //關閉文件 close(fd); return 0; }View Code
這是我在ubuntu上運行的結果,但是有個奇怪的地方就是我在Windows下打開文件的時候沒有看到後面寫進去的內容,而且出現亂碼,在ubuntu下用cat命令卻能看到文件中的全部內容,並且沒有亂碼
- 用cat命令打開文件
- 終端輸出
- windowns下打開