linux文件编程(open、write、read、creat、lseek函数)
文件編程內(nèi)容比較多,如文件系統(tǒng)原理及訪問機制文件在內(nèi)核中的管理機制,什么是文件信息節(jié)點iNode、文件共享、文件權(quán)限、各種用戶對其權(quán)限等等。以下主要記錄如何用代碼操作文件,實現(xiàn)文件的創(chuàng)建、打開、編輯等自動化執(zhí)行。
文件描述符介紹、其中標準輸入是從鍵盤獲取輸入寫到0(標準輸入文件),然后標準輸出是將1(標準輸出文件)內(nèi)容輸出出來,2(標準錯誤)是可以將程序運行過程中的錯誤放到標準錯誤中。文件描述符的作用域就是當前進程,出了這個文件進程就沒有了意義。
文件分為靜態(tài)文件和動態(tài)文件:
- 文件存放在塊設(shè)備(磁盤)的文件系統(tǒng)中的文件中,我們稱之為靜態(tài)文件。文件存放在內(nèi)存中,我們稱之為動態(tài)文件。
- 當程序open一個文件時linux內(nèi)核會做以下操作:首先內(nèi)核會建立一個打開文件的數(shù)據(jù)結(jié)構(gòu)(包含文件描述符,節(jié)點信息等),記錄我們打開的文件。然后會向內(nèi)存申請一段內(nèi)存,并且將靜態(tài)文件里面的內(nèi)容從塊設(shè)備讀取到內(nèi)核中特定地址管理存放。
- 當打開文件后,對文件進行讀寫操作,都是在內(nèi)存中這一份動態(tài)文件進行操作,而不是針對靜態(tài)文件。此時修改動態(tài)文件的內(nèi)容,并不會影響靜態(tài)文件里面的內(nèi)容,兩者是不同步的。當close文件時,close內(nèi)部的內(nèi)核會將動態(tài)文件里面的內(nèi)容更新到塊設(shè)備的靜態(tài)文件中。
- 為什么要這樣設(shè)計?不直接對塊設(shè)備進行操作?
因為塊設(shè)備的讀寫速度相對內(nèi)存慢,是按塊為單位進行操作,不靈活。而內(nèi)存是按字節(jié)為單位進行操作的,而且可以隨機操作,很靈活。
操作系統(tǒng)提供了一系列的API
如Linux系統(tǒng):
- 打開文件用open函數(shù)
- 讀寫文件用write/read函數(shù)
- 光標定位用lseek函數(shù)
- 關(guān)閉用close函數(shù)(如果不關(guān)閉,會造成文件的損壞)
文件的打開/創(chuàng)建(open函數(shù)):
在linux終端要善于使用man手冊,如果想要查找open函數(shù)如何使用,可在man手冊中查找(比如:man 2 open即可查找到open函數(shù)的用法):
大佬博客:open函數(shù)、linux中的9個權(quán)限位
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() {int fd1;int fd2;fd1=open("./locallinuxfile1",O_RDWR);//"./locallinuxfile1"是字符串,而字符串本身就是指針,符合open函數(shù)對參數(shù)的要求printf("fd1=%d\n",fd1);//當文件存在時返回文件的描述符,不存在時返回-1if(fd1==-1){printf("打開失敗\n");//以下方式可以在文件不存在的時候創(chuàng)建文件//fd2=open("/home/fhn/linuxfiletest/linuxfile3",O_CREAT|O_RDWR,0600); 這個是不在當前路徑創(chuàng)建 fd2=open("./locallinuxfile1",O_CREAT|O_RDWR,0600);//在當前路徑創(chuàng)建文件printf("fd2=%d\n",fd2);if(fd2>0){printf("文件創(chuàng)建成功\n");}}return 0; } 以上代碼當文件不存在的時候會自動創(chuàng)建文件,文件存在時會直接輸出打開文件的描述符。ls -l命令可查看文件的所有者和文件類型、文件最后修改時間等等 fhn@ubuntu:~/linuxfile$ ls -l total 16 -rw------- 1 fhn fhn 0 Jun 26 16:54 locallinuxfile1 -rwxrwxr-x 1 fhn fhn 8392 Jun 26 16:54 makeopenfile -rw-rw-r-- 1 fhn fhn 617 Jun 26 16:54 makeopenfile.c各個符號代表的意思,轉(zhuǎn)至上面的大佬博客:linux中的9個權(quán)限位fd2=open("./locallinuxfile1",O_CREAT|O_RDWR,0600); 這行代碼中的0600是什么意思? 一般地文件操作的權(quán)限就試一下幾種: 1、可讀 r 4 2、可寫 w 2 3、可執(zhí)行 x 1 0600其中的6表示4+2就是可讀可寫的權(quán)限 通過ls -l也可以看出rw就是可讀可寫的權(quán)限。0600就是給文件所有者對創(chuàng)建文件的權(quán)限 6是表示給文件所有者的權(quán)限 第二個0表示同組的主用戶 第三個0表示其他組的大佬博客:Linux文件權(quán)限4位數(shù)字含義、文件權(quán)限數(shù)字是什么意思
寫入文件(write函數(shù))
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);第一個參數(shù)是文件描述符(就是一個文件的標識符),第二個參數(shù)是緩沖區(qū)(無指針),第三個參數(shù)是要寫入文件的字節(jié)數(shù)。 這個函數(shù)可以簡單理解為:將buf指向的緩沖區(qū)中的count個字節(jié)寫入到文件中。如果寫入成功返回整形數(shù)(寫入文件的字節(jié)數(shù)),寫入失敗則返回-1。示例:
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main() {int fd;int returnbuf;char* name=NULL;name=(char*)malloc(128);printf("請輸入要寫入文件的姓名:\n");scanf("%s",name);fd=open("./loacallinuxfile",O_RDWR|O_CREAT,0600);if(fd==-1){printf("文件打開失敗\n");perror("open");}returnbuf=write(fd,name,strlen(name));//將內(nèi)容寫入文件close(fd);//關(guān)閉文件printf("寫入文件的字節(jié)數(shù)是:%d\n",returnbuf);//sizeof(name)是計算指針的大小,而不是計算name指向地址的大小//而要計算字符串的長度則用strlen()return 0; }read函數(shù):
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 第一個參數(shù)是文件描述符,第二個參數(shù)是緩沖區(qū),第三個參數(shù)是要從文件里面讀多少字節(jié)到緩沖區(qū)中。 read函數(shù)讀的時候是從光標向后讀指定的字節(jié)數(shù)。示例:
#include<stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() {int fd;int readbuf;char* buf;buf=(char*)malloc(128);fd=open("./locallinuxfile",O_RDWR|O_CREAT);if(fd==-1){printf("文件打開失敗\n");perror("open");}readbuf=read(fd,buf,4);printf("從文件中讀取的字節(jié)是:%s,字節(jié)數(shù)是:%d\n",buf,readbuf);return 0; }lseek函數(shù):
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence); 第一個參數(shù)是文件描述符,第二個參數(shù)是偏移值,第三個參數(shù)是表示偏移量相對于哪個位置進行偏移。 返回值是相對文件頭的偏移量,可以間接的用lseek計算文件的大小,只需將光標指向文件尾部。通常第三個參數(shù)有以下幾個宏: SEEK_SET:指向文件的頭 SEEK_CUR:指向文件的當前位置 SEEK_END:指向文件的尾 lseek(fd,0,SEEK_SET); lseek(fd,0,SEEK_END);write、read和lseek綜合使用:
#include<stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() {int fd;int n_write;int n_read;char* writebuf;char* readbuf;writebuf=(char*)malloc(128);printf("請輸入要寫入的姓名:\n");scanf("%s",writebuf);readbuf=(char*)malloc(strlen(writebuf)+1);fd=open("./locallinuxfile",O_CREAT|O_RDWR,0600);if(fd==-1){printf("文件打開失敗\n");perror("open");}n_write=write(fd,writebuf,strlen(writebuf));if(n_write==-1){printf("文件寫入失敗\n");perror("write");}lseek(fd,-n_write,SEEK_CUR); //read函數(shù)讀的時候是從光標向后讀指定的字節(jié)數(shù),當寫完后光標在文件最后所以讀不到東西,所以要用lseek函數(shù)n_read=read(fd,readbuf,n_write);if(n_read==-1){printf("文件讀取失敗\n");perror("read");}close(fd);printf("文件中寫入了:%s,字節(jié)數(shù)是:%d\n",writebuf,n_write);printf("從文件中讀取了:%s,字節(jié)數(shù)是:%d\n",readbuf,n_read);return 0; }文件創(chuàng)建函數(shù)creat函數(shù):
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int creat(const char *pathname, mode_t mode); 第一個參數(shù)是要創(chuàng)建的文件名(包含路徑、缺省為當前路徑) 第二個參數(shù)是:創(chuàng)建模式 (針對三種用戶設(shè)置:所處用戶,所處用戶組,其他用戶權(quán)限:讀,寫,執(zhí)行)//可讀可寫可執(zhí)行常見的差創(chuàng)建模式: 宏表示 數(shù)字 S_IRUSR 4 可讀 S_IWUSR 2 可寫 S_IXUSR 1 可執(zhí)行 S_IRWXU 7 可讀、寫、執(zhí)行(也可以用數(shù)字代替,如0777)若創(chuàng)建成功返回創(chuàng)建文件的文件描述符,創(chuàng)建失敗返回-1,demo:
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() {int fd;fd=creat("./file",S_IRWXU);if(fd==-1){printf("fail");perror("creat");}return 0; }總結(jié)
以上是生活随笔為你收集整理的linux文件编程(open、write、read、creat、lseek函数)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一阶段结束考核题(链表的嵌套使用)
- 下一篇: java学习(84):object常用方