Linux文件IO操作

      網(wǎng)友投稿 835 2025-04-01

      文件操作是linux系統(tǒng)中最常見(jiàn)的操作之一,關(guān)于文件的輸入輸出操作,分為基于文件描述符的I/O操作和基于流的I/O操作。本篇介紹基于文件描述符的I/O操作。

      文件類型

      首先介紹下linux系統(tǒng)中文件的各種類型與符號(hào)表示。

      基于文件描述符的I/O操作

      文件描述符

      Linux操作系統(tǒng)內(nèi)核利用文件描述符來(lái)訪問(wèn)文件,文件描述符是一個(gè)非負(fù)整數(shù),用于描述被打開(kāi)文件的索引值,它指向該文件的相關(guān)信息記錄表。

      文件描述符的有效范圍是0到1023,其中0、1、2分別用于標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)出錯(cuò)。

      文件重定向

      重定向標(biāo)準(zhǔn)輸出

      不使用系統(tǒng)標(biāo)準(zhǔn)輸出的默認(rèn)設(shè)備,而是將輸出結(jié)果直接寫(xiě)在一個(gè)新的文件中,命令格式如下:

      command 1> filename # 把標(biāo)準(zhǔn)輸出重定向到filename文件中 command > filename # 把標(biāo)準(zhǔn)輸出重定向到filename文件中 command >> filename # 把標(biāo)準(zhǔn)輸出重定向到filename文件中,方式是追加在現(xiàn)有內(nèi)容的后面 > myfile # 創(chuàng)建一個(gè)長(zhǎng)度為0的空文件

      command代表用戶所熟悉的shell命令

      重定向標(biāo)準(zhǔn)輸入

      不使用系統(tǒng)標(biāo)準(zhǔn)輸入的默認(rèn)設(shè)備,而是引用其它文件的內(nèi)容或是其它命令的輸出,命令格式如下:

      command < filename # 以filename文件的內(nèi)容作為command命令的標(biāo)準(zhǔn)輸入 command < file1 > file2 # 以file1文件的內(nèi)容作為command命令的標(biāo)準(zhǔn)輸入,并以file2文件的內(nèi)容作為command命令的標(biāo)準(zhǔn)輸出 command << delimiter # 從標(biāo)準(zhǔn)輸入中讀入,直到遇到delimiter分界符

      重定向標(biāo)準(zhǔn)出錯(cuò)

      將系統(tǒng)指向的錯(cuò)誤信息重定向到一個(gè)文件中,而不使用默認(rèn)的顯示器等輸出設(shè)備,命令格式如下:

      command 2> filename # 把標(biāo)準(zhǔn)出錯(cuò)信息重定向到filename文件中 command 2>> filename # 把標(biāo)準(zhǔn)出錯(cuò)信息重定向到filename文件中(追加)

      文件的創(chuàng)建、打開(kāi)、關(guān)閉

      open()函數(shù)

      調(diào)用該函數(shù)可以打開(kāi)或創(chuàng)建一個(gè)文件,函數(shù)原型為:

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

      運(yùn)行成功返回文件描述符,運(yùn)行出錯(cuò)返回-1。

      參數(shù)flag用于描述文件的打開(kāi)方式。

      參數(shù)mode用于指定所創(chuàng)建文件的權(quán)限。

      使用open函數(shù)打開(kāi)或創(chuàng)建一個(gè)文件,open_file.c:

      #include #include #include #include #include #include #define FLAGS O_WRONLY|O_CREAT|O_TRUNC #define MODE S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH int main(void) { const char *pathname; int fd; char pn[30]; printf("Input the pathname[<30 strings]:"); gets(pn); pathname = pn; if((fd = open(pathname, FLAGS, MODE)) == -1) { printf("error, open file failed!\n"); exit(1); } printf("OK, open file successful!\n"); printf("fd=%d\n", fd); return 0; }

      編譯后執(zhí)行:

      $ ./open_file Input the pathname[<30 strings]:./hello.txt OK, open file successful! fd=3

      程序在當(dāng)前目錄創(chuàng)建了hello.txt文件,進(jìn)一步查看該文件的信息:

      ls -l hello.txt -rwxr-xr-x 1 deeplearning deeplearning 0 12月 20 19:59 hello.txt

      可以看到文件的權(quán)限為rwxr-xr-x,與程序中的MODE宏定義一致。

      create()函數(shù)

      用于創(chuàng)建文件,函數(shù)原型為:

      #include #include #include int creat(const char *pathname, mode_t mode);

      運(yùn)行成功返回以只寫(xiě)方式打開(kāi)的文件描述符,運(yùn)行出錯(cuò)返回-1。

      close()函數(shù)

      用于關(guān)閉文件,函數(shù)原型為:

      #include int close(int fd);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      文件的定位

      每個(gè)已打開(kāi)的文件都有一個(gè)與其相關(guān)聯(lián)的“當(dāng)前文件位移量”,它是一個(gè)非負(fù)整數(shù),用以度量從文件開(kāi)始處計(jì)算的字節(jié)數(shù)。可以調(diào)用lseek()函數(shù)顯示地定位一個(gè)打開(kāi)文件,函數(shù)原型為:

      #include #include off_t lseek(int fd, off_t offset, int whence);

      運(yùn)行成功返回文件位移量,運(yùn)行出錯(cuò)返回-1。

      測(cè)試標(biāo)準(zhǔn)輸入能否被設(shè)置位移量,offset_test.c:

      #include #include #include #include int main(void) { if(lseek(0, 0, SEEK_CUR) == -1) printf("can't seek!\n"); else printf("seek OK!\n"); exit(0); }

      編譯后執(zhí)行:

      $ ./offset_test can't seek! $ ./offset_test < ./hello.txt seek OK!

      可以看出,對(duì)于標(biāo)準(zhǔn)輸入,一般不能設(shè)置位移量,而用戶創(chuàng)建的一般文件可以設(shè)置位移量。

      文件的讀寫(xiě)

      read()函數(shù)

      Linux文件IO操作

      用read()函數(shù)從打開(kāi)文件中讀取數(shù)據(jù),函數(shù)原型為:

      #include ssize_t read(int fd, void *buf, size_t count);

      運(yùn)行成功返回讀到的字節(jié)數(shù),若已到文件尾返回0,運(yùn)行出錯(cuò)返回-1。

      參數(shù)fd表示文件描述符,參數(shù)buf為指向緩沖區(qū)的指針,參數(shù)count表示本次操作將要讀取的字節(jié)數(shù)。

      實(shí)際讀取的字節(jié)數(shù)有時(shí)會(huì)少于要求讀取的字節(jié)數(shù):

      讀普通文件時(shí),在讀到要求的字節(jié)數(shù)之前到達(dá)文件尾

      從終端設(shè)備讀時(shí),通常一次讀取一行

      從網(wǎng)絡(luò)中讀時(shí),網(wǎng)絡(luò)中的緩沖機(jī)構(gòu)可能造成返回值小于所要求讀的字節(jié)數(shù)

      write()函數(shù)

      用write()函數(shù)向打開(kāi)文件中寫(xiě)數(shù)據(jù),函數(shù)原型為:

      #include ssize_t write(int fd, void *buf, size_t count);

      運(yùn)行成功返回已寫(xiě)的字節(jié)數(shù),運(yùn)行出錯(cuò)返回-1。

      參數(shù)fd表示文件描述符,參數(shù)buf為指向緩沖區(qū)的指針,參數(shù)count表示本次操作將要寫(xiě)入的字節(jié)數(shù)。

      函數(shù)返回值通常與參數(shù)count的值相同,否則表示出錯(cuò)。出錯(cuò)的原因通常是磁盤已寫(xiě)滿或超過(guò)了對(duì)一個(gè)給定進(jìn)程的文件長(zhǎng)度限制。

      使用write函數(shù)向文件寫(xiě)入數(shù)據(jù),write_file.c:

      #include #include #include #include #include #include #include #define FILENAME "./hello.txt" #define SIZE 80 #define FLAGS O_RDWR|O_APPEND int main(void) { int count; int fd; char write_buf[SIZE]; const char *pathname = FILENAME; if((fd=open(pathname, FLAGS)) == -1) { printf("error, open file failed!\n"); exit(1); } printf("OK, open file successful!\n"); printf("Begin Write:\n"); gets(write_buf); count = strlen(write_buf); if(write(fd, write_buf, count) == -1) { printf("error, write file failed!\n"); exit(1); } printf("OK, write %d strings to file!\n", count); return 0; }

      編譯后執(zhí)行:

      $ ./write_file OK, open file successful! Begin Write: hello,linux C! OK, write 14 strings to file!

      查看hello.txt:

      $ cat hello.txt hello,linux C!

      文件的屬性操作

      改變文件訪問(wèn)權(quán)限

      chmod()、fchmod()這兩個(gè)函數(shù)使用戶可以更改現(xiàn)存文件的存取許可權(quán):

      #include #include int chmod(conts char *pathname, mode_t mode); int fchmod(int fd, mode_t mode);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      chmod(),在指定的文件上進(jìn)行操作,pathname指定了文件的絕對(duì)或相對(duì)路徑名

      fchmod(),在已打開(kāi)的文件上進(jìn)行操作,fd是文件描述符,mode為文件的權(quán)限

      使用chmod函數(shù)改變文件的訪問(wèn)權(quán)限,change_mode.c:

      #include #include #include #include #include #define FILENAME "./hello.txt" #define MODE 0700 int main(void) { const char *pathname = FILENAME; if(chmod(pathname, MODE) == -1) { printf("error, change failed!\n"); exit(1); } printf("OK, change successful!\n"); return 0; }

      編譯后執(zhí)行:

      $ ./change_mode OK, change successful!

      進(jìn)一步查看該文件的信息:

      $ ls -l hello.txt -rwx------ 1 deeplearning deeplearning 14 12月 20 20:09 hello.txt

      可以看到文件的權(quán)限為rwxr-----,與程序中的MODE宏定義(0755)一致。

      改變文件所有者

      有3個(gè)函數(shù)可以改變一個(gè)文件的所有者識(shí)別號(hào)和用戶組識(shí)別號(hào),函數(shù)原型如下:

      #include #include int chown(const char *pathname, uid_t owner, git_t group); int fchown(int fd, uid_t owner, git_t group); int lchown(const char *pathname, uid_t owner, git_t group);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      chown(),修改指定文件的所有者

      fchown(),修改已打開(kāi)文件的所有者

      lchown(),修改符號(hào)鏈接文件本身的所有者

      重命名

      對(duì)文件或目錄文件重命名,函數(shù)原型:

      #include int rename(const char *oldname, const char *newname);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      修改文件的長(zhǎng)度

      截短文件可以調(diào)用truncate()和ftruncate(),函數(shù)原型如下:

      #include #include int truncate(const char *pathname, off_t len); int ftruncate(int fd, off_t len);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      文件的其它操作

      stat、fsat、lstat函數(shù)

      Linux系統(tǒng)中所有文件都有一個(gè)與之對(duì)應(yīng)的索引節(jié)點(diǎn),該節(jié)點(diǎn)包含了文件的相關(guān)信息,這些信息被保存在stat結(jié)構(gòu)體中,可以調(diào)用下面3個(gè)stat函數(shù)來(lái)返回文件的信息:

      #include #include int state(const char *pathname, struct stat *sbuf); int fstate(int fd, struct stat *sbuf); int lstate(const char *pathname, struct stat *sbuf);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      stat結(jié)構(gòu)體基本形式如下:

      struct stat { mode_t st_mode; // 文件類型&模式 ino_t st_ino; // i-node號(hào) dev_t st_dev; // 設(shè)備號(hào) dev_t st_rdev; // 設(shè)備號(hào)(特殊文件) nlink_t st_nlinkl;// 鏈接號(hào) uid_t st_uid; // 用戶ID gid_t st_gid; // 組ID off_t st_size; time_t st_atime; // access time_t st_mtime; // modification time_t st_ctime; // file station change unsigned long st_blksize; unsigned long st_blocks; }

      dup、dup2函數(shù)

      這兩個(gè)函數(shù)可以用來(lái)復(fù)制一個(gè)現(xiàn)存的文件描述符,原型如下:

      #include int dup(int fd); int dup2(int fd, int fd2);

      運(yùn)行成功返回新的文件描述符,運(yùn)行出錯(cuò)返回-1。

      fcntl函數(shù)

      該函數(shù)可以改變已打開(kāi)文件的性質(zhì),原型如下:

      #include #include #include int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg);

      運(yùn)行成功依賴于cmd,運(yùn)行出錯(cuò)返回-1。

      sync、fsync函數(shù)

      為保證磁盤上實(shí)際文件系統(tǒng)與緩存中內(nèi)容的一致性,Linux系統(tǒng)提供了兩個(gè)系統(tǒng)調(diào)用函數(shù),原型如下:

      #include void sync(void); int fsync(int fd);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      特殊文件的操作

      目錄文件的操作

      mkdir、rmdir函數(shù)

      mkdir用于創(chuàng)建目錄,原型如下:

      #include #include int mkdir(const char *pathname, mode_t mode);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      rmdir用于刪除目錄,原型如下:

      #include int rmdir(const char *pathname);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      opendir 、closedir、readdir函數(shù)

      opendir用于打開(kāi)目錄,原型如下:

      #include #include DIR *opendir(const char *pathname);

      運(yùn)行成功返回指針,運(yùn)行出錯(cuò)返回NULL。

      closedir用于關(guān)閉目錄,原型如下:

      #include #include int closedir(DIR *dp);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      readdir用于讀取目錄,原型如下:

      #include #include struct dirent *readdir(DIR *dp);

      運(yùn)行成功返回指針,運(yùn)行出錯(cuò)返回NULL。

      函數(shù)返回值指向的結(jié)構(gòu)體指針定義為:

      struct dirent { ino_t d_ino; char d_name[NAME_MAX+1]; }

      chdir、fchdir、getcwd函數(shù)

      進(jìn)程調(diào)用chdir或fchdir函數(shù)可以更改當(dāng)前工作目錄,函數(shù)原型如下:

      #include int chdir(const char *pathname); int fchdir(int fd);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      這兩個(gè)函數(shù),可以分別用pathname或文件描述符來(lái)指定新的當(dāng)前工作目錄。

      獲取當(dāng)前工作目錄的絕對(duì)路徑,使用getcwd函數(shù),函數(shù)原型為:

      #include char *getcwd(char *buf, size_t size);

      運(yùn)行成功返回buf,運(yùn)行出錯(cuò)返回NULL。

      向此函數(shù)傳遞兩個(gè)參數(shù),一個(gè)是緩存地址buf,另一個(gè)是緩存的長(zhǎng)度size,該緩存必須有足夠的長(zhǎng)度以容納絕對(duì)路徑名再加上一個(gè)NULL終止符,否則返回出錯(cuò)。

      改變并獲取當(dāng)前的工作目錄,change_path.c:

      #include #include #include #include #include #include #define SIZE 30 int main(void) { char newpath[SIZE]; char buf[SIZE]; printf("Input the new pathname[<30 strings]:"); gets(newpath); if(chdir(newpath) == -1) { printf("error, change directory failed!\n"); exit(1); } printf("OK, change directory successful!\n"); if(getcwd(buf, SIZE) == NULL) { printf("error, getcwd failed!\n"); exit(1); } printf("cwd=%s\n", buf); return 0; }

      先查看當(dāng)前的工作目錄:

      $ pwd /home/deeplearning/dcj/linuxCTest/fileIO

      編譯后執(zhí)行:

      $ ./change_path Input the new pathname[<30 strings]:/home/deeplearning OK, change directory successful! cwd=/home/deeplearning

      再次使用pwd查看當(dāng)前的工作目錄,理論上應(yīng)該已經(jīng)切換到新的目錄(但是我這里測(cè)試沒(méi)有切換成功,原因未知)。

      鏈接文件的操作

      硬鏈接

      創(chuàng)建一個(gè)硬鏈接使用link函數(shù),原型如下:

      #include int link(const char *pathname1, const char *pathname2);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      此函數(shù)創(chuàng)建一個(gè)新目錄項(xiàng)pathname2,它引用現(xiàn)存文件pathname1,若pathname2已存在則返回出錯(cuò)。

      硬鏈接要求兩文件路徑位于同一文件系統(tǒng)中,且只有超級(jí)用戶root才可以創(chuàng)建指向一個(gè)目錄的新鏈接。

      刪除一個(gè)硬鏈接使用unlink函數(shù),原型如下:

      #include int unlink(const char *pathname);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      也可以使用remove函數(shù)解除對(duì)一個(gè)文件或目錄的連接。對(duì)于文件,remove的功能與unlink相同,對(duì)于目錄,remove的功能與rmdir相同。

      #include int remove(const char *pathname);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      符號(hào)鏈接

      符號(hào)鏈接是對(duì)一個(gè)文件的間接指針。

      symlink函數(shù)用于創(chuàng)建一個(gè)符號(hào)鏈接,原型如下:

      #include int symlink(const char *actualpath, const char *sympath);

      運(yùn)行成功返回0,運(yùn)行出錯(cuò)返回-1。

      參考:《精通Linux C編程》- 程國(guó)鋼

      Linux

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:快速在同一或不同Excel工作表中輸入相同數(shù)據(jù)的方法(在電子表格中快速輸入相同數(shù)據(jù)的方法是)
      下一篇:Excel2019怎么替換數(shù)據(jù)?Excel2019替換數(shù)據(jù)教程
      相關(guān)文章
      亚洲精品国产第1页| 久久青草亚洲AV无码麻豆| 亚洲精品中文字幕乱码影院| 国产偷v国产偷v亚洲高清| 超清首页国产亚洲丝袜| 亚洲日本中文字幕一区二区三区| 理论亚洲区美一区二区三区| 亚洲AV无码国产精品永久一区| 亚洲AV日韩AV无码污污网站| 蜜臀亚洲AV无码精品国产午夜.| 亚洲a∨国产av综合av下载| 亚洲国产欧美一区二区三区| 亚洲AV综合永久无码精品天堂| 亚洲成av人在线观看网站 | 亚洲国产国产综合一区首页| 亚洲AV永久无码精品水牛影视| 亚洲精品无码久久久久| 亚洲AV日韩AV高潮无码专区| 亚洲专区在线视频| 亚洲欧洲日本精品| 精品亚洲国产成人| 亚洲人成色77777在线观看| 亚洲AV成人片无码网站| 亚洲国产成人久久综合野外| 国产亚洲精品资在线| 久久国产亚洲精品麻豆| 亚洲一区二区在线免费观看| 亚洲理论片在线中文字幕| 亚洲人成网站看在线播放| 亚洲色成人网站WWW永久四虎| 亚洲爆乳成av人在线视菜奈实| 亚洲精品色在线网站| 亚洲人成网站色在线入口| 亚洲精品V欧洲精品V日韩精品 | 中文字幕亚洲码在线| 国产精品亚洲一区二区在线观看 | 久久亚洲色一区二区三区| 亚洲av福利无码无一区二区| 亚洲经典在线中文字幕| 亚洲视频在线观看2018| 综合偷自拍亚洲乱中文字幕|