1. 程式人生 > >linux中檔案I-O操作(系統I-O)

linux中檔案I-O操作(系統I-O)

我們都知道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下開啟