linux中檔案I-O操作(系統I-O)
阿新 • • 發佈:2019-02-12
我們都知道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下開啟