linux文件編程(open、write、read、creat、lseek函數)

文件編程內容比較多,如文件系統原理及訪問機制文件在內核中的管理機制,什么是文件信息節點iNode、文件共享、文件權限、各種用戶對其權限等等。以下主要記錄如何用代碼操作文件,實現文件的創建、打開、編輯等自動化執行。

文件描述符介紹、其中標準輸入是從鍵盤獲取輸入寫到0(標準輸入文件),然后標準輸出是將1(標準輸出文件)內容輸出出來,2(標準錯誤)是可以將程序運行過程中的錯誤放到標準錯誤中。文件描述符的作用域就是當前進程,出了這個文件進程就沒有了意義。

文件分為靜態文件和動態文件:

  • 文件存放在塊設備(磁盤)的文件系統中的文件中,我們稱之為靜態文件。文件存放在內存中,我們稱之為動態文件。
  • 當程序open一個文件時linux內核會做以下操作:首先內核會建立一個打開文件的數據結構(包含文件描述符,節點信息等),記錄我們打開的文件。然后會向內存申請一段內存,并且將靜態文件里面的內容從塊設備讀取到內核中特定地址管理存放。
  • 當打開文件后,對文件進行讀寫操作,都是在內存中這一份動態文件進行操作,而不是針對靜態文件。此時修改動態文件的內容,并不會影響靜態文件里面的內容,兩者是不同步的。當close文件時,close內部的內核會將動態文件里面的內容更新到塊設備的靜態文件中。
  • 為什么要這樣設計?不直接對塊設備進行操作?
    因為塊設備的讀寫速度相對內存慢,是按塊為單位進行操作,不靈活。而內存是按字節為單位進行操作的,而且可以隨機操作,很靈活。

操作系統提供了一系列的API
如Linux系統:

  • 打開文件用open函數
  • 讀寫文件用write/read函數
  • 光標定位用lseek函數
  • 關閉用close函數(如果不關閉,會造成文件的損壞)

文件的打開/創建(open函數):
在linux終端要善于使用man手冊,如果想要查找open函數如何使用,可在man手冊中查找(比如:man 2 open即可查找到open函數的用法):

       #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>
以上三個是使用open函數要包含的頭文件。int open(const char *pathname, int flags);這個函數第一個參數是要打開的文件名(含路徑,缺省為當前路徑)第二個參數Flags是對文件操作的權限1、O_RDONLY:只讀打開2、O_WRONLY:只寫打開3、O_RDWR:可讀可寫打開當我們附帶權限后,開開文件就只能按照這種權限來操作。以上三個權限應當指定一個。下列常量是可選用的的(用的時候要用或操作符):O_CREAT:若文件不存在則創建它,使用此選項時,需要同時說明第三個參數mode,用其說明該新文件的存取許可權限。O_EXCL:如果同時指定了O_CREAT,而文件已經存在則出錯返回值是-1。O_APPEND:每次寫時都加到文件的尾端。如果不加這個常量每次寫的時候就會將源文件內容覆蓋掉一定的字節數(寫入多少字節數就在源文件覆蓋多少字節)如果用或操作加上這個常量,會在原文件另起一行,將東西寫入O_TRUNC:屬性去打開文件時,如果這個文件中本來是有內容的,而且為只讀或只寫成功打開,則將其長度截短為0。 就是將源文件中的所有內容都干掉,就沒有內容了。open函數的返回值是文件描述符(整型數),是相當于對打開的這個文件的一個標記,后面可以用這個文件描述符對文件進行讀寫操作。int open(const char *pathname, int flags, mode_t mode);Mode:一定是在flags中使用了O_CREAT標志,mode記錄待創建文件的訪問權限位。對于 這種形式的open 函數來說,第三個參數僅當創建新文件時才使用,用于指定文件的訪問權限位

大佬博客:open函數、linux中的9個權限位

#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函數對參數的要求printf("fd1=%d\n",fd1);//當文件存在時返回文件的描述符,不存在時返回-1if(fd1==-1){printf("打開失敗\n");//以下方式可以在文件不存在的時候創建文件//fd2=open("/home/fhn/linuxfiletest/linuxfile3",O_CREAT|O_RDWR,0600);	這個是不在當前路徑創建			fd2=open("./locallinuxfile1",O_CREAT|O_RDWR,0600);//在當前路徑創建文件printf("fd2=%d\n",fd2);if(fd2>0){printf("文件創建成功\n");}}return 0;
}
以上代碼當文件不存在的時候會自動創建文件,文件存在時會直接輸出打開文件的描述符。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各個符號代表的意思,轉至上面的大佬博客:linux中的9個權限位fd2=open("./locallinuxfile1",O_CREAT|O_RDWR,0600);
這行代碼中的0600是什么意思?
一般地文件操作的權限就試一下幾種:
1、可讀     r    4
2、可寫     w    2
3、可執行   x    1
0600其中的6表示4+2就是可讀可寫的權限
通過ls -l也可以看出rw就是可讀可寫的權限。0600就是給文件所有者對創建文件的權限
6是表示給文件所有者的權限
第二個0表示同組的主用戶
第三個0表示其他組的

大佬博客:Linux文件權限4位數字含義、文件權限數字是什么意思

寫入文件(write函數)

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);第一個參數是文件描述符(就是一個文件的標識符),第二個參數是緩沖區(無指針),第三個參數是要寫入文件的字節數。
這個函數可以簡單理解為:將buf指向的緩沖區中的count個字節寫入到文件中。如果寫入成功返回整形數(寫入文件的字節數),寫入失敗則返回-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));//將內容寫入文件close(fd);//關閉文件printf("寫入文件的字節數是:%d\n",returnbuf);//sizeof(name)是計算指針的大小,而不是計算name指向地址的大小//而要計算字符串的長度則用strlen()return 0;
}

read函數:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
第一個參數是文件描述符,第二個參數是緩沖區,第三個參數是要從文件里面讀多少字節到緩沖區中。
read函數讀的時候是從光標向后讀指定的字節數。

示例:

#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("從文件中讀取的字節是:%s,字節數是:%d\n",buf,readbuf);return 0;
}

lseek函數:

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
第一個參數是文件描述符,第二個參數是偏移值,第三個參數是表示偏移量相對于哪個位置進行偏移。
返回值是相對文件頭的偏移量,可以間接的用lseek計算文件的大小,只需將光標指向文件尾部。通常第三個參數有以下幾個宏:
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函數讀的時候是從光標向后讀指定的字節數,當寫完后光標在文件最后所以讀不到東西,所以要用lseek函數n_read=read(fd,readbuf,n_write);if(n_read==-1){printf("文件讀取失敗\n");perror("read");}close(fd);printf("文件中寫入了:%s,字節數是:%d\n",writebuf,n_write);printf("從文件中讀取了:%s,字節數是:%d\n",readbuf,n_read);return 0;
}

文件創建函數creat函數:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
第一個參數是要創建的文件名(包含路徑、缺省為當前路徑)
第二個參數是:創建模式 (針對三種用戶設置:所處用戶,所處用戶組,其他用戶權限:讀,寫,執行)//可讀可寫可執行常見的差創建模式:
宏表示        數字      
S_IRUSR       4       可讀
S_IWUSR       2       可寫
S_IXUSR       1       可執行
S_IRWXU       7       可讀、寫、執行(也可以用數字代替,如0777)若創建成功返回創建文件的文件描述符,創建失敗返回-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;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272236.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272236.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272236.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

記憶化搜索,FatMouse and Cheese

題目鏈接&#xff1a;http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode1107 http://acm.hdu.edu.cn/showproblem.php?pid1078 1、從gird[0][0]出發&#xff0c;每次的方向搜索一下&#xff0c;每次步數搜索一下 for(i0; i<4; i) {for(j1; j<k; j){int tx…

九種跨域方式實現原理(完整版)

前言前后端數據交互經常會碰到請求跨域&#xff0c;什么是跨域&#xff0c;以及有哪幾種跨域方式&#xff0c;這是本文要探討的內容。一、什么是跨域&#xff1f;1.什么是同源策略及其限制內容&#xff1f;同源策略是一種約定&#xff0c;它是瀏覽器最核心也最基本的安全功能&a…

文件編程練習

自己實現linux CP指令 實現cp指令的思路&#xff1a; 打開要復制的原文件讀原文件的內容到buf打開或者創建要粘貼的文件將buf里面的內容寫到目標文件關閉兩個文件 main 函數的標準原型&#xff1a; main 函數的標準原型應該是 int main(int argc, char *argv[]);argc 是命令…

java.lang.OutOfMemoryError: GC overhead limit exceeded

今天現場weblogic報java.lang.OutOfMemoryError: GC overhead limit exceeded&#xff0c;在metalink查了下&#xff0c;有明白解釋&#xff0c;要設置一個JVM參數。只是因為當前weblogic內存設置為4G&#xff0c;所以設置參數的做法事實上并非解決這個問題之道。還是要分析web…

[翻譯] Visual Studio 2019 RC版發布

今天&#xff0c;我們將分享 Visual Studio 2019 的發布候選版(RC 版) - 這是在 4 月 2 日的虛擬發布活動上正式發布之前的最后步驟之一。 您可以在 visualstudio.com/downloads 下載 RC 版。與往常一樣&#xff0c;查看RC 版的發行說明以獲取更多詳細信息。發布候選版的說明在…

fread、fwrite、fopen函數的簡單使用和open、read、write區別解析

這幾個函數的區別&#xff1a;fread、fwrite、fopen和open、read、write區別解析 標準C庫函數的簡單使用 fopen函數原型&#xff1a; #include <stdio.h> FILE *fopen(const char *pathname, const char *mode);第一個參數是&#xff1a;要打開的文件路徑 第二個參數是…

docker安裝rocketmq你學會了嗎

防火墻開通端口 9876 10911 9800 firewall-cmd --zonepublic --add-port9876/tcp --permanent firewall-cmd --zonepublic --add-port10911/tcp --permanent firewall-cmd --zonepublic --add-port9800/tcp --permanent firewall-cmd --reload 創建存儲文件夾 mkdir -p /root…

程序員的編程能力與編程年齡

作者丨酷殼/陳皓&#xff0c; http://coolshell.cn/articles/10688.html程序員這個職業究竟可以干多少年&#xff0c;在中國這片神奇的土地上&#xff0c;很多人都說只能干到30歲&#xff0c;然后就需要轉型&#xff0c;就像《程序員技術練級攻略》這篇文章很多人回復到這種玩…

Rocketmq集群架構圖

集群架構圖 集群特點

進程相關概念、C程序的空間分配

進程的定義&#xff1a; “進程”是操作系統的最基本、最重要的概念之一。但迄今為止對這一概念還沒有一個確切的統一的描述。下面給出幾種對進程的定義描述。 進程是程序的一次執行。進程是可以并行執行的計算。進程是一個程序與其使用的數據在處理機上順序執行時發生的活動。…

(精)C#中TransactionScope的使用方法和原理

標簽&#xff1a;.net transactionscope原創作品&#xff0c;允許轉載&#xff0c;轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://cnn237111.blog.51cto.com/2359144/1271600在.net 1.1的時代&#xff0c;還沒有TransactionScope…

一文搞定并發面試題

1、Object 的 wait()和notify() 方法下圖為線程狀態的圖&#xff1a;Object 對象中的 wait()和notify()是用來實現實現等待 / 通知模式。其中等待狀態和阻塞狀態是不同的。等待狀態的線程可以通過notify() 方法喚醒并繼續執行&#xff0c;而阻塞狀態的線程則是等待獲取新的鎖。…

fork、vfork、wait、waitpid

fork函數&#xff1a; 一個進程&#xff0c;包括代碼、數據和分配給進程的資源。fork&#xff08;&#xff09;函數通過系統調用創建一個與原來進程幾乎完全相同的進程&#xff0c;也就是兩個進程可以做完全相同的事&#xff0c;但如果初始參數或者傳入的變量不同&#xff0c;兩…

java解析xml

<?xml version"1.0" encoding"UTF-8"?> <mimetype><default><mime-type>text/html</mime-type></default><mime-mapping><extension>zip</extension><mime-type>application/zip</mime-…

Linux常見英文報錯中文翻譯(菜鳥必知)

Linux常見英文報錯中文翻譯(菜鳥必知)1.command not found 命令沒有找到2.No such file or directory 沒有這個文件或目錄3.Permission denied 權限不足4.No space left on device 磁盤沒有剩余空間5.File exists 文件已經存在6.Is a directory 這是1個目錄7.Not a directory 不…

阿里開源分布式事務seata帶你入門

介紹 Seata 是阿里巴巴開源的分布式事務中間件&#xff0c;一種分布式事務解決方案&#xff0c;具有高性能和易于使用的微服務架構。 1:對業務無侵入&#xff1a;即減少技術架構上的微服務化所帶來的分布式事務問題對業務的侵入 2:高性能&#xff1a;減少分布式事務解決方案…

exec族函數、system函數、popen函數、PATH

exec族函數函數的作用&#xff1a; 我們用fork函數創建新進程后&#xff0c;經常會在新進程中調用exec函數去執行另外一個程序。當進程調用exec函數時&#xff0c;該進程被完全替換為新程序&#xff08;在exec都后面的代碼不會被得到執行&#xff09;。因為調用exec函數并不創建…

jquery.validate.unobtrusive的使用

應用 一、引入 <script src"Scripts/jquery-1.7.1.min.js"></script> <script src"Scripts/jquery.validate.js"></script> <script src"Scripts/jquery.validate.unobtrusive.js"></script> 二、1&#xf…