檔案IO
不帶緩存的IO函數:
open
,
read
,
write
,
lseek
和
close
。每個函數對應核心的一個系統調用,這些函數不是C語言标準,但屬于POSIX接口。
檔案描述符
對Linux而言,所有的打開檔案都由檔案描述符引用。檔案描述符是一個非負整數。當用
open
,
creat
打開檔案時,傳回檔案描述符,對檔案的讀寫操作通過檔案描述符進行。
按照慣例,檔案描述符0與程序的标準輸入結合,檔案描述符1與标準輸出結合,檔案描述符2與标準錯誤結合。在POSIX中,
、
1
、
2
用符号常數
STDIN_FILENO
、
STDOUT_FILENO
、
STDERR_FILENO
代替。這些常數定義在
<unistd.h>
中。
open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char* pathname, int o_flag, .../*, mode_t mode */);
-
: 要打開或建立的檔案的名字pathname
-
: 打開檔案标志(定義在o_flag
creat函數
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *pathname, mode_t mode); //成功時傳回檔案描述符,否則傳回-1
早期的
open
函數隻能打開已有的檔案,需要用
creat
函數建立檔案,而且
creat
建立檔案的同時也以隻寫的方式打開了檔案。相當于
open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)
;
close
用close函數關閉一個打開檔案。
#include <unistd.h>
int close(int filedes);
關閉一個檔案時也釋放該程序加在該檔案的所有記錄鎖。當一個程序終止時,他的所有打開檔案都由核心關閉。
lseek
每個打開檔案都有一個與其關聯的“目前檔案位移量“。它是一個非負整數,用來度量從檔案開始處計算的位元組數。當打開一個檔案時,位移量為0。lseek顯式地定位一個打開檔案的位移,該操作隻改變了作業系統維護的值,不會有實際的IO操作。
以讀寫方式打開的檔案使用一個偏移量,讀或寫都會改變改偏移量。如果使用了O_APPEND标志,每次寫入後都會把偏移量移到末尾。
在打開檔案表裡每個表項有一個目前檔案位移量成員。而檔案描述符複制的結果是兩個檔案描述父共用一個位移量。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence); //成功時傳回新的檔案偏移,否則為-1。
filedes是要定位的檔案的檔案描述父,whence是基準位置,offset是以基準的偏移量。whence的取值:
- SEEK_SET: 檔案開頭。
- SEEK_CUR: 目前偏移量
- SEEK_END: 檔案末尾加一的位置。
不是所有的檔案都可以用lseek定位偏移,比如管道就不行。
read
#include <unistd.h>
ssize_t read(int filedes, void* buf, size_t n); //成功時傳回讀到的位元組數(包括0),出錯傳回-1。
讀資料時預設是阻塞的,如果open時指定O_NONBLOCK那麼是非阻塞的。
有多種情況下,讀取到的位元組數小于指定的位元組數:
- 讀普通檔案是,快到檔案末尾。
- 從終端讀取資料,預設時一次最多一行
- 從網絡中讀時,網絡的部分資料沒到達,隻讀取到達的資料。
讀操作執行完之後,檔案的偏移量後移實際讀得的位元組數。
write
#include <unistd.h>
ssize_t write(int filedes, const void* buf, size_t n); //成功時傳回寫入的位元組數,出錯為-1
寫入後檔案偏移後移寫入位元組數。如果打開時O_APPEND選項,則每次寫入時都會自動将偏移移動到末尾再寫入。
注:為了保證完整寫入,需要檢查傳回值是否與n相等。