簡介
函式名: lseek
頭檔案:#include <sys/types.h> #include <unistd.h>
用 法: off_t lseek(int handle, off_t offset, int fromwhere);
所有打開的檔案都有一個當前檔案偏移量(current file offset),以下簡稱為 cfo。cfo 通常是一個非負整數,用於表明檔案開始處到檔案當前位置的位元組數。讀寫操作通常開始於 cfo,並且使 cfo 增大,增量為讀寫的位元組數。檔案被打開時,cfo 會被初始化為 0,除非使用了 O_APPEND 。
使用 lseek 函式可以改變檔案的 cfo 。
lseek 的以下用法返回當前的偏移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
這個技巧也可用於判斷我們是否可以改變某個檔案的偏移量。如果參數 fd(檔案描述符)指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 並且置 errno 為 ESPIPE。
對於普通檔案(regular file),cfo 是一個非負整數。但對於特殊設備,cfo 有可能是負數。因此,我們不能簡單地測試 lseek 的返回值是否小於 0 來判斷 lseek 成功與否,而應該測試 lseek 的返回值是否等於 -1 來判斷 lseek 成功與否。
lseek 僅將 cfo 保存於核心中,不會導致任何 I/O 操作。這個 cfo 將被用於之後的讀寫操作。
如果 offset 比檔案的當前長度更大,下一個寫操作就會把檔案“撐大(extend)”。這就是所謂的在檔案里創造“空洞(hole)”。沒有被實際寫入檔案的所有位元組由重複的 0 表示。空洞是否占用硬碟空間是由檔案系統(file system)決定的。
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
int handle;
char msg[]="This is a test";
char ch;
/*create a file*/
handle=open("TEST.$$$",O_CREAT|O_RDWR,S_IREAD|S_IWRITE);
/*write some data to the file*/
write(handle,msg,strlen(msg));//檔案中寫入字元串,即This is a test
/*seek to the begining of the file*/
lseek(handle,0,SEEK_SET);//重定向到檔案開始
/*reads chars from the file until we hit EOF*/
while(read(handle,&ch,1) > 0)//!=EOF和>=0都不行 read函式返回的是實際讀取字元的位數
{
printf("%c",ch);
}
close(handle);
return 0;
}
Linux C
相關函式
dup,open,fseek
表頭檔案
#include<sys/types.h>
#include<unistd.h>
定義函式
off_t lseek(int filde,off_t offset ,int whence);
函式說明
每一個已打開的檔案都有一個讀寫位置,當打開檔案時通常其讀寫位置是指向檔案開頭,若是以附加的方式打開檔案(如O_APPEND),則讀寫位置會指向檔案尾。當read()或write()時,讀寫位置會隨之增加,lseek()便是用來控制該檔案的讀寫位置。參數fildes 為已打開的檔案描述詞,參數offset 為根據參數whence來移動讀寫位置的位移數。
Offset:偏移量,每一讀寫操作所需要移動的距離,單位是位元組的數量,可正可負(向前移,向後移)。
參數
whence為下列其中一種:(SEEK_SET,SEEK_CUR和SEEK_END和依次為0,1和2).
SEEK_SET 將讀寫位置指向檔案頭後再增加offset個位移量。
SEEK_CUR 以目前的讀寫位置往後增加offset個位移量。
SEEK_END 將讀寫位置指向檔案尾後再增加offset個位移量。
當whence 值為SEEK_CUR 或SEEK_END時,參數offet允許負值的出現。
下列是較特別的使用方式:
1) 欲將讀寫位置移到檔案開頭時:
lseek(int fildes,0,SEEK_SET);
2) 欲將讀寫位置移到檔案尾時:
lseek(int fildes,0,SEEK_END);
3) 想要取得目前檔案位置時:
lseek(int fildes,0,SEEK_CUR);
返回值
當調用成功時則返回目前的讀寫位置,也就是距離檔案開頭多少個位元組。若有錯誤則返回-1,errno 會存放錯誤代碼。
可能設定erron的錯誤代碼:
EBADF: fildes不是一個打開的檔案描述符。
ESPIPE:檔案描述符被分配到一個管道、套接字或FIFO。
EINVAL:whence取值不當。
附加說明
Linux系統不允許lseek()對tty裝置作用,此項動作會令lseek()返回ESPIPE。
SEEK_SET 等同於數字0 例如 :lseek(int fildes,0,SEEK_SET);=lseek(int fildes,0,0);
SEEK_CUR 等同於數字1 例如 :lseek(int fildes,0,SEEK_CUR);=lseek(int fildes,0,1);
SEEK_END 等同於數字2 例如 :lseek(int fildes,0,SEEK_END);=lseek(int fildes,0,2);