C語言-系統-文件操作

1. Linux 文件

Linux 常見的文件類型:普通文件、目錄文件、設備文件、管道文件、套接字和鏈接文件等等。它們的分別用 -、d、c、p、s和 l 表示。


圖片1
  1. 普通文件
    普通文件是指普通計算機用戶看到的文件,它們常駐留在磁盤的某處。通常分為文本文件和二進制文件。
    文本文件:以文本的某種編碼形式存儲在存儲器中,它是以“行”為基本結構的一種信息組織和存儲方式。
    二進制文件:以文本的二進制形式存儲才在計算機中,用戶一般不能直接讀懂它們,只能通過相應的軟件才能將其顯示出來。二進制文件一般是可執行程序、圖形、圖像、聲音等等。
  2. 目錄文件
    目錄文件:主要目的是用于管理和組織系統中的大量文件。它存儲一組相關文件的位置、大小等與文件相關的信息。
  3. 設備文件
    設備文件:Linux系統把每一個I/O設備都看成一個文件,與普通文件一樣處理;可以細分為塊設備文件(表示文件系統高速緩存的設備,例如硬盤驅動器)和字符設備文件(表示非高速緩存的設備,例如鼠標、系統終端)。前者的存取是以一個個字符塊為單位的,后者則是以單個字符為單位的。
  4. 管道文件
    管道文件:主要用于在進程間傳遞數據。管道文件又稱先進先出(FIFO)文件。管道文件只針對兩個進程間的通信而設計,建立管道的時候,實際獲得兩個文件描述符:一個用于讀取而另一個用于寫入。任何寫入管道寫入端的數據都可以從讀取端讀出。
  5. 套接字文件
    套接字文件:類似于管道文件。管道文件用于本地通信,而套接字允許網絡上的通信。
  6. 鏈接文件
    鏈接文件:這個文件包含了另一個文件的路徑名。被連接的文件可以是任意文件和目錄,可以連接不同文件系統的文件,鏈接文件甚至可以連接不存在的文件,這就產生“斷鏈”的問題,鏈接文件甚至可以循環鏈接自己。

2. 文件的操作

Linux 最常用的文件操作系統調用包括:創建、打開文件 open()和create(),關閉文件close(),讀取文件read(),寫入文件write(),移動文件指針lseek(),文件控制fcntl()和access()。

1. 創建打開文件

open():
頭文件:#include<sys/types.h>/<sys/stat.h>/<fcntl.h>
函數的一般形式:

    int open(const char * pathname, int flags);
    int open(const char * pathname, int flags, mode_t mode);

參數設置:

  1. pathname:是文件路徑
  2. flags:文件打開的方式
O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR 以可讀寫方式打開文件. 上述三種旗標是互斥的, 也就是不可同時使用, 但可與下列的旗標利用OR(|)運算符組合.
O_CREAT 若欲打開的文件不存在則自動建立該文件.
O_EXCL 如果O_CREAT 也被設置, 此指令會去檢查文件是否存在. 文件若不存在則建立該文件, 否則將導致打開文件錯誤. 此外, 若O_CREAT 與O_EXCL 同時設置, 并且欲打開的文件為符號連接, 則會打開文件失敗.
O_NOCTTY 如果欲打開的文件為終端機設備時, 則不會將該終端機當成進程控制終端機.
O_TRUNC 若文件存在并且以可寫的方式打開時, 此旗標會令文件長度清為0, 而原來存于該文件的資料也會消失.
O_APPEND 當讀寫文件時會從文件尾開始移動, 也就是所寫入的數據會以附加的方式加入到文件后面.
O_NONBLOCK 以不可阻斷的方式打開文件, 也就是無論有無數據讀取或等待, 都會立即返回進程之中.
O_NDELAY 同O_NONBLOCK.
O_SYNC 以同步的方式打開文件.
O_NOFOLLOW 如果參數pathname 所指的文件為一符號連接, 則會令打開文件失敗.
O_DIRECTORY 如果參數pathname 所指的文件并非為一目錄, 則會令打開文件失敗 //注:此為Linux2. 2 以后特有的旗標, 以避免一些系統安全問題. 
  1. mode: 則有下列數種組合, 只有在建立新文件時才會生效, 此外真正建文件時的權限會受到umask 值所影響, 因此該文件權限應該為 (mode-umaks)。
S_IRWXU00700 權限, 代表該文件所有者具有可讀、可寫及可執行的權限.
S_IRUSR 或S_IREAD, 00400 權限, 代表該文件所有者具有可讀取的權限.
S_IWUSR 或S_IWRITE, 00200 權限, 代表該文件所有者具有可寫入的權限.
S_IXUSR 或S_IEXEC, 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 權限, 代表其他用戶具有可執行的權限.

返回值:成功返回文件描述符,失敗返回 -1。
錯誤代碼:

EEXIST 參數pathname 所指的文件已存在, 卻使用了O_CREAT 和O_EXCL 旗標.
EACCESS 參數pathname 所指的文件不符合所要求測試的權限.
EROFS 欲測試寫入權限的文件存在于只讀文件系統內.
EFAULT 參數pathname 指針超出可存取內存空間.
EINVAL 參數mode 不正確.
ENAMETOOLONG 參數 pathname 太長.
ENOTDIR 參數pathname 不是目錄.
ENOMEM 核心內存不足.
ELOOP 參數pathname 有過多符號連接問題.
EIO I/O 存取錯誤.

2. 關閉文件

close():
頭文件:#include<unsitd.h>
函數的一般形式:int close(int fd);
參數設置:

fd:想要關閉的文件的文件描述。

返回值:成功返回0,失敗返回 -1。
錯誤代碼:EBADF 參數fd 非有效的文件描述詞或該文件已關閉。

3. 讀取文件

read():
頭文件:#include<unsitd.h>
函數的一般形式:ssize_t read(int fd, void * buf, size_t count);
參數設置:

fd:要讀取的文件的文件描述;
buf:讀取的字符放在buf指針所指的內存中;
count:要讀取的字符數。

返回值:成功返回讀取的實際字節數,失敗返回 -1。
錯誤代碼:

EINTR 此調用被信號所中斷.
EAGAIN 當使用不可阻斷I/O 時(O_NONBLOCK), 若無數據可讀取則返回此值.
EBADF 參數fd 非有效的文件描述詞, 或該文件已關閉.

4. 寫入文件

write():
頭文件:#include<unsitd.h>
函數的一般形式:ssize_t write (int fd, const void * buf, size_t count);
參數設置:

fd:要寫入文件的文件描述;
buf:寫入的字符放在buf指針所指的內存中;
count:要寫入的字符數。

返回值:成功返回寫入的實際字節數,失敗返回 -1。
錯誤代碼:

EINTR 此調用被信號所中斷.
EAGAIN 當使用不可阻斷I/O 時 (O_NONBLOCK), 若無數據可讀取則返回此值.
EADF 參數fd 非有效的文件描述詞, 或該文件已關閉.

5. 文件隨機存取

lseek():
頭文件:#include <sys/types.h> #include <unistd.h>
函數的一般形式:off_t lseek(int fildes, off_t offset, int whence);
參數設置:

fildes:已打開的文件描述符
offset:根據參數whence來移動讀寫位置的位移數。
whence:文件內容指針的位置

    SEEK_SET 參數offset 即為新的讀寫位置.
    SEEK_CUR 以目前的讀寫位置往后增加offset 個位移量.
    SEEK_END 將讀寫位置指向文件尾后再增加offset 個位移量. 當whence 值為SEEK_CUR 或SEEK_END 時, 參數offet 允許負值的出現.

返回值:當調用成功時則返回目前的讀寫位置, 也就是距離文件開頭多少個字節. 若有錯誤則返回-1。

// 常用的使用方法:
1) 欲將讀寫位置移到文件開頭時:lseek(int fildes, 0, SEEK_SET);
2) 欲將讀寫位置移到文件尾時:lseek(int fildes, 0, SEEK_END);
3) 想要取得目前文件位置時:lseek(int fildes, 0, SEEK_CUR);

3. 案例

#include <stdio.h>
#include <stdlib.h>  //exit
#include <string.h> //memset
#include <unistd.h>  // read(),write(),close()
// open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
  int fd = -1, num = -1;
  char buf[10];
  fd = open("./myfile.text", O_RDWD | O_CREAT); //打開文件,若沒有文件,則在當前目錄下創建該文件
  if (-1 == fd)
  {
    perror("open:");
    exit(1);
  }
  printf("input buf[10]:");
  scanf("%s", buf);
  write(fd, buf, sizeof(buf));  //寫入文件當中
  memset(buf, '\0', 10); //清空buf[10]
  printf("after clear buf:%s\n", buf);
  lseek(fd, 0, SEEK_SET); //文件指針跳轉到文件頭
  num = read(fd, buf, sizeof(buf)); //讀取文件中的內容
  if (-1 == num)
  {
    perror("read:");
    exit(1);
  }
  printf("read ./myfile.text message num :%d\n", num);
  close(fd);  //關閉文件描述符
  return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容