1. Linux 文件
Linux 常見的文件類型:普通文件载慈、目錄文件惭等、設(shè)備文件、管道文件办铡、套接字和鏈接文件等等辞做。它們的分別用 -、d寡具、c秤茅、p、s和 l 表示童叠。
- 普通文件
普通文件是指普通計算機(jī)用戶看到的文件框喳,它們常駐留在磁盤的某處。通常分為文本文件和二進(jìn)制文件厦坛。
文本文件:以文本的某種編碼形式存儲在存儲器中五垮,它是以“行”為基本結(jié)構(gòu)的一種信息組織和存儲方式。
二進(jìn)制文件:以文本的二進(jìn)制形式存儲才在計算機(jī)中粪般,用戶一般不能直接讀懂它們拼余,只能通過相應(yīng)的軟件才能將其顯示出來。二進(jìn)制文件一般是可執(zhí)行程序亩歹、圖形匙监、圖像、聲音等等小作。 - 目錄文件
目錄文件:主要目的是用于管理和組織系統(tǒng)中的大量文件亭姥。它存儲一組相關(guān)文件的位置、大小等與文件相關(guān)的信息顾稀。 - 設(shè)備文件
設(shè)備文件:Linux系統(tǒng)把每一個I/O設(shè)備都看成一個文件达罗,與普通文件一樣處理;可以細(xì)分為塊設(shè)備文件(表示文件系統(tǒng)高速緩存的設(shè)備,例如硬盤驅(qū)動器)和字符設(shè)備文件(表示非高速緩存的設(shè)備粮揉,例如鼠標(biāo)巡李、系統(tǒng)終端)。前者的存取是以一個個字符塊為單位的扶认,后者則是以單個字符為單位的侨拦。 - 管道文件
管道文件:主要用于在進(jìn)程間傳遞數(shù)據(jù)。管道文件又稱先進(jìn)先出(FIFO)文件辐宾。管道文件只針對兩個進(jìn)程間的通信而設(shè)計狱从,建立管道的時候,實(shí)際獲得兩個文件描述符:一個用于讀取而另一個用于寫入叠纹。任何寫入管道寫入端的數(shù)據(jù)都可以從讀取端讀出季研。 - 套接字文件
套接字文件:類似于管道文件。管道文件用于本地通信誉察,而套接字允許網(wǎng)絡(luò)上的通信与涡。 - 鏈接文件
鏈接文件:這個文件包含了另一個文件的路徑名。被連接的文件可以是任意文件和目錄持偏,可以連接不同文件系統(tǒng)的文件递沪,鏈接文件甚至可以連接不存在的文件,這就產(chǎn)生“斷鏈”的問題综液,鏈接文件甚至可以循環(huán)鏈接自己。
2. 文件的操作
Linux 最常用的文件操作系統(tǒng)調(diào)用包括:創(chuàng)建儒飒、打開文件 open()和create()谬莹,關(guān)閉文件close(),讀取文件read()桩了,寫入文件write()附帽,移動文件指針lseek(),文件控制fcntl()和access()井誉。
1. 創(chuàng)建打開文件
open():
頭文件:#include<sys/types.h>/<sys/stat.h>/<fcntl.h>
函數(shù)的一般形式:
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
參數(shù)設(shè)置:
- pathname:是文件路徑
- flags:文件打開的方式
O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR 以可讀寫方式打開文件. 上述三種旗標(biāo)是互斥的, 也就是不可同時使用, 但可與下列的旗標(biāo)利用OR(|)運(yùn)算符組合.
O_CREAT 若欲打開的文件不存在則自動建立該文件.
O_EXCL 如果O_CREAT 也被設(shè)置, 此指令會去檢查文件是否存在. 文件若不存在則建立該文件, 否則將導(dǎo)致打開文件錯誤. 此外, 若O_CREAT 與O_EXCL 同時設(shè)置, 并且欲打開的文件為符號連接, 則會打開文件失敗.
O_NOCTTY 如果欲打開的文件為終端機(jī)設(shè)備時, 則不會將該終端機(jī)當(dāng)成進(jìn)程控制終端機(jī).
O_TRUNC 若文件存在并且以可寫的方式打開時, 此旗標(biāo)會令文件長度清為0, 而原來存于該文件的資料也會消失.
O_APPEND 當(dāng)讀寫文件時會從文件尾開始移動, 也就是所寫入的數(shù)據(jù)會以附加的方式加入到文件后面.
O_NONBLOCK 以不可阻斷的方式打開文件, 也就是無論有無數(shù)據(jù)讀取或等待, 都會立即返回進(jìn)程之中.
O_NDELAY 同O_NONBLOCK.
O_SYNC 以同步的方式打開文件.
O_NOFOLLOW 如果參數(shù)pathname 所指的文件為一符號連接, 則會令打開文件失敗.
O_DIRECTORY 如果參數(shù)pathname 所指的文件并非為一目錄, 則會令打開文件失敗 //注:此為Linux2. 2 以后特有的旗標(biāo), 以避免一些系統(tǒng)安全問題.
- mode: 則有下列數(shù)種組合, 只有在建立新文件時才會生效, 此外真正建文件時的權(quán)限會受到umask 值所影響, 因此該文件權(quán)限應(yīng)該為 (mode-umaks)蕉扮。
S_IRWXU00700 權(quán)限, 代表該文件所有者具有可讀、可寫及可執(zhí)行的權(quán)限.
S_IRUSR 或S_IREAD, 00400 權(quán)限, 代表該文件所有者具有可讀取的權(quán)限.
S_IWUSR 或S_IWRITE, 00200 權(quán)限, 代表該文件所有者具有可寫入的權(quán)限.
S_IXUSR 或S_IEXEC, 00100 權(quán)限, 代表該文件所有者具有可執(zhí)行的權(quán)限.
S_IRWXG 00070 權(quán)限, 代表該文件用戶組具有可讀颗圣、可寫及可執(zhí)行的權(quán)限.
S_IRGRP 00040 權(quán)限, 代表該文件用戶組具有可讀的權(quán)限.
S_IWGRP 00020 權(quán)限, 代表該文件用戶組具有可寫入的權(quán)限.
S_IXGRP 00010 權(quán)限, 代表該文件用戶組具有可執(zhí)行的權(quán)限.
S_IRWXO 00007 權(quán)限, 代表其他用戶具有可讀喳钟、可寫及可執(zhí)行的權(quán)限.
S_IROTH 00004 權(quán)限, 代表其他用戶具有可讀的權(quán)限
S_IWOTH 00002 權(quán)限, 代表其他用戶具有可寫入的權(quán)限.
S_IXOTH 00001 權(quán)限, 代表其他用戶具有可執(zhí)行的權(quán)限.
返回值:成功返回文件描述符,失敗返回 -1在岂。
錯誤代碼:
EEXIST 參數(shù)pathname 所指的文件已存在, 卻使用了O_CREAT 和O_EXCL 旗標(biāo).
EACCESS 參數(shù)pathname 所指的文件不符合所要求測試的權(quán)限.
EROFS 欲測試寫入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi).
EFAULT 參數(shù)pathname 指針超出可存取內(nèi)存空間.
EINVAL 參數(shù)mode 不正確.
ENAMETOOLONG 參數(shù) pathname 太長.
ENOTDIR 參數(shù)pathname 不是目錄.
ENOMEM 核心內(nèi)存不足.
ELOOP 參數(shù)pathname 有過多符號連接問題.
EIO I/O 存取錯誤.
2. 關(guān)閉文件
close():
頭文件:#include<unsitd.h>
函數(shù)的一般形式:int close(int fd);
參數(shù)設(shè)置:
fd:想要關(guān)閉的文件的文件描述奔则。
返回值:成功返回0,失敗返回 -1蔽午。
錯誤代碼:EBADF 參數(shù)fd 非有效的文件描述詞或該文件已關(guān)閉易茬。
3. 讀取文件
read():
頭文件:#include<unsitd.h>
函數(shù)的一般形式:ssize_t read(int fd, void * buf, size_t count);
參數(shù)設(shè)置:
fd:要讀取的文件的文件描述;
buf:讀取的字符放在buf指針?biāo)傅膬?nèi)存中及老;
count:要讀取的字符數(shù)抽莱。
返回值:成功返回讀取的實(shí)際字節(jié)數(shù)范抓,失敗返回 -1。
錯誤代碼:
EINTR 此調(diào)用被信號所中斷.
EAGAIN 當(dāng)使用不可阻斷I/O 時(O_NONBLOCK), 若無數(shù)據(jù)可讀取則返回此值.
EBADF 參數(shù)fd 非有效的文件描述詞, 或該文件已關(guān)閉.
4. 寫入文件
write():
頭文件:#include<unsitd.h>
函數(shù)的一般形式:ssize_t write (int fd, const void * buf, size_t count);
參數(shù)設(shè)置:
fd:要寫入文件的文件描述食铐;
buf:寫入的字符放在buf指針?biāo)傅膬?nèi)存中匕垫;
count:要寫入的字符數(shù)。
返回值:成功返回寫入的實(shí)際字節(jié)數(shù)璃岳,失敗返回 -1年缎。
錯誤代碼:
EINTR 此調(diào)用被信號所中斷.
EAGAIN 當(dāng)使用不可阻斷I/O 時 (O_NONBLOCK), 若無數(shù)據(jù)可讀取則返回此值.
EADF 參數(shù)fd 非有效的文件描述詞, 或該文件已關(guān)閉.
5. 文件隨機(jī)存取
lseek():
頭文件:#include <sys/types.h> #include <unistd.h>
函數(shù)的一般形式:off_t lseek(int fildes, off_t offset, int whence);
參數(shù)設(shè)置:
fildes:已打開的文件描述符
offset:根據(jù)參數(shù)whence來移動讀寫位置的位移數(shù)。
whence:文件內(nèi)容指針的位置
SEEK_SET 參數(shù)offset 即為新的讀寫位置.
SEEK_CUR 以目前的讀寫位置往后增加offset 個位移量.
SEEK_END 將讀寫位置指向文件尾后再增加offset 個位移量. 當(dāng)whence 值為SEEK_CUR 或SEEK_END 時, 參數(shù)offet 允許負(fù)值的出現(xiàn).
返回值:當(dāng)調(diào)用成功時則返回目前的讀寫位置, 也就是距離文件開頭多少個字節(jié). 若有錯誤則返回-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); //打開文件,若沒有文件犁柜,則在當(dāng)前目錄下創(chuàng)建該文件
if (-1 == fd)
{
perror("open:");
exit(1);
}
printf("input buf[10]:");
scanf("%s", buf);
write(fd, buf, sizeof(buf)); //寫入文件當(dāng)中
memset(buf, '\0', 10); //清空buf[10]
printf("after clear buf:%s\n", buf);
lseek(fd, 0, SEEK_SET); //文件指針跳轉(zhuǎn)到文件頭
num = read(fd, buf, sizeof(buf)); //讀取文件中的內(nèi)容
if (-1 == num)
{
perror("read:");
exit(1);
}
printf("read ./myfile.text message num :%d\n", num);
close(fd); //關(guān)閉文件描述符
return 0;
}