<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux基礎(chǔ) ——’文件編程‘是怎么回事?

          共 16893字,需瀏覽 34分鐘

           ·

          2022-04-11 11:31


          LINUX基礎(chǔ) ——文件編程篇

          「Linux 一切皆是文件 文件系統(tǒng)(文件夾/文件)硬件設(shè)備 ,管道,數(shù)據(jù)庫,Socket等」

          一、文件編程概述:

          1.應(yīng)用中比如:「賬單,游戲進(jìn)度,配置文件等。」2.用代碼操作文件:「實(shí)現(xiàn)文件創(chuàng)建,打開,編輯等自動(dòng)化執(zhí)行?!?/strong>

          二、計(jì)算機(jī)如何幫我們自動(dòng)化完成以上操作呢?

          操作系統(tǒng)提供了一系列的API ?如Linux系統(tǒng):

          打開 ? ? ? ? ? ? open

          讀寫 ? ? ? ? ? ? write/read

          光標(biāo)定位 ? ? ?lseek

          關(guān)閉 ? ? ? ? ? ? ?close

          三、文件打開及創(chuàng)建

          打開/創(chuàng)建文件

          頭文件:

          「#include #include #include

          int open(const char *pathname , int flags); //(參數(shù)1:字符指針 指向文件路徑 , 參數(shù)2:整型數(shù)權(quán)限)

          int open(const char *pathname , int ?flags , mode_t ?mode); //open 返回值是文件描述符——沒有文件返回值就無法用write(); ?和 ?read();

          參數(shù)說明:

          *pathname ?: ? //要打開的文件名(含路徑,缺省為當(dāng)前路徑)

          flags ? :

          • O_RDONLY ? ?只讀打開
          • O_WRONLY ? 只寫打開
          • O_RDWR ? ? ? 可讀可寫可打卡

          「當(dāng)我們附帶了權(quán)限后,打開的文件就只能按照這種權(quán)限來操作?!?/strong>「以上這三個(gè)常數(shù)中應(yīng)當(dāng)只指定一個(gè)?!?/strong>

          int?creat(const?char?*filename?,?mode_t?mode)
          filename:要?jiǎng)?chuàng)建的文件名(包含路徑,缺省為當(dāng)前路徑)
          mode:創(chuàng)建模式??//可讀可寫可執(zhí)行

          常見創(chuàng)建模式:

          ?宏表示???????數(shù)字
          ?S_IRUSR???????4??????可讀
          ?S_IWUSR???????2??????可寫
          ?S_IXUSR???????1??????可執(zhí)行
          ?S_IRWXU???????7??????可讀,寫,執(zhí)行?

          示例代碼:(在路徑/Home/CLC/下創(chuàng)建了file1可讀可寫可執(zhí)行文件)

          #include
          #include
          #include
          #include
          #include

          int?main()
          {
          ???int?fd;
          ???char?*buf?=?"test";
          ???fd?=?creat("/home/CLC/file",S_IRWXU);???//S_IRWXU??可讀可寫可執(zhí)行
          ???return?0;
          }

          ==「下列常數(shù)是可選擇的:」==

          1. O_CREA //若文件不存在則創(chuàng)建它。

          使用此選項(xiàng)時(shí),「需要同時(shí)說明第三個(gè)參數(shù)mode,用其說明該新文件的存取許可權(quán)限?!?/strong>
          「mode:一定是在flags中使用了O_CREAT標(biāo)志,mode記錄待創(chuàng)建的文件的訪問權(quán)限。」

          「O_CREAT 若文件不存在則創(chuàng)建它 ? 示例代碼:」

          #include
          #include
          #include
          #include

          int?main()
          {
          ???int?fd;????//定義整型返回值
          ???fd?=?open("./file",O_RDWR);??//open指令?打開可讀可寫file文件返回值
          ???printf("fd?=?%d\n",fd);
          ???if(fd?==?-1){?????????//若返回值為-1??沒有file文件
          ??????printf("open?file?failed\n");
          ??????fd?=?open("./file"?,?O_RDWR?|?O_CREAT?,?0600);???
          ??????//open?指令?若沒有file文件?”?|?O_CREAT?”?創(chuàng)建file文件?權(quán)限0600??6=4+2??所以是rw??可讀可寫
          ??????if(fd>0){
          ??????????printf("creat?file?success\n");
          ??????}???
          ???}
          ???printf("fd=%d\n?,fd");
          ???return?0;
          }

          結(jié)果:

          「注意:」

          「fd = open("./file",O_RDWR);」 ? ? //open指令 打開可讀可寫file文件返回值

          「fd = open("./file" , O_RDWR ?| O_CREAT , 0600);」
          // ?open 指令 若沒有file文件 ” | O_CREAT ” 創(chuàng)建file文件 權(quán)限0600 ?6=4+2 ?所以是rw ?可讀可寫

          權(quán)限0600的含義:

          「—表示普通文件 r (4) 可讀 ? ?w(2)可寫 rw 表示可讀可寫 ?x(1)執(zhí)行」「0600 :6=4+2 所以是rw 可讀可寫 0是同組 0其他組」

          2. O_EXCL //如果同時(shí)指定了OCREAT , 而文件已經(jīng)存在,則打開失敗或者返回-1

          「O_EXCL ?//如果同時(shí)指定了OCREAT , 而文件已經(jīng)存在,則打開失敗或者返回-1 ? 示例代碼:」

          #include
          #include
          #include
          #include

          int?main(){
          ???int?fd;
          ???fd?=?open("./file",O_RDWR?|?O_CREAT?|?O_EXCL?,?0600);
          ???if(fd?==?-1){?????//若返回值為-1??沒有file文件
          ?????printf("file?exist\n");
          ?????return?0;
          ???}
          }

          注意:

          「fd = open("./file",O_RDWR | O_CREAT | O_EXCL , 0600);」

          3. O_APPEND//每次寫時(shí)都加到文件的尾端。

          「O_APPEND //每次寫時(shí)都加到文件的尾端 ?示例代碼:」

          #include
          #include
          #include
          #include

          int??main(){
          ???int?fd;
          ???char?*buf?=?"19990330";
          ???
          ???fd?=?open("./file",O_RDWR?|?O_APPEND);
          ???
          ???printf("open?susceess:?fd?=?%d?\n",?fd);
          ???
          ???int?n_write?=?write(fd?,buf,strlen(buf));
          ???
          ???if(n_write?!=?-1){
          ??????????printf("write?%d?byte?to?file\n",n_write);
          ???}
          ???close(fd);
          ???return?0;
          }

          注意:

          「fd = open("./file",O_RDWR | O_APPEND);」

          4. O_TRUNC屬性去打開文件時(shí),如果這個(gè)文件中本來是有內(nèi)容的,而且為只讀或者只寫 成功打開,則將其長度截?cái)酁?。

          「O_TRUNC屬性去打開文件時(shí),如果這個(gè)文件中本來是有內(nèi)容的,把原先內(nèi)容全部覆蓋掉,示例代碼:」

          #include
          #include
          #include
          #include

          int?main(){
          ??int?fd;
          ??char?*buf?="19990330";
          ??
          ??fd?=?open("./file",O_RDWR?|?O_TRUNC);
          ??printf("open?susceess:fd?=%d\n",fd);
          ??int?n_write?=?write(fd?,buf?,strlen(buf));
          ??if(n_write?!=?-1){
          ????????printf("write?%d?bute?to?file\n",n_write);
          ??}
          ??close(fd);
          ??return?0;
          }

          注意:

          「fd = open("./file",O_RDWR | O_TRUNC);」

          ls-l ?是把文件所有內(nèi)容列出來

          -rwxr-xr-x 1 CLC book ?8478 ?Fed 9 12:36 ?mode -rw-r --r -- 1 CLC book ? 385 ? ?Fed 9 12:36 ?mode.c -rw ------ 1 CLC ? book ? ? 0 ? ? ?Fed 9 12:44 ?file

          —表示普通文件 r (4) 可讀 w(2)可寫 rw 表示可讀可寫 x(1)執(zhí)行

          四、文件寫入操作編程

          寫入文件:==「write」== 頭文件: ? ?==「#include==

          「ssize_t write」 (int fd , const void *buf , size_t count);
          ==「//將緩沖區(qū)buf指針指向內(nèi)存數(shù)據(jù),寫conuct的大小 到 fd里?!?/strong>==

          (int fd , const void *buf , size_t count) 參數(shù):(文件描述符 ,【無類型指針是一個(gè)緩沖區(qū)】,寫入文件的大?。?/p>

          文件寫入操作示例代碼:

          #include
          #include
          #include
          #include
          #include
          #include

          int?main()
          {
          ????int?fd;
          ????char?*buf?=?"Refuel.CONG";
          ????fd?=?open("./file",O_RDWR);
          ????printf("fd=%d\n",fd);
          ????if(fd?==?-1){
          ????????printf("open?file?failed\n");
          ????????fd?=?open("./file",O_RDWR?|?O_CREAT?,?0600);
          ????????if(fd>0){
          ????????????printf("creat?file?success\n");
          ????????}
          ????}
          ????//ssize_t?write(int?fd?,?const?void?*buf?,?size_t?count);
          ????//將緩沖區(qū)buf指針指向內(nèi)存數(shù)據(jù),寫conut大小到fd。
          ????write(fd,buf,strlen(buf));
          ????printf("fd=%d\n",fd);
          ????close(fd);???//關(guān)閉fd文件
          ????return?0
          }

          strlen(); 函數(shù)是用來 真正計(jì)算有效字符長度用strlen 頭文件是:

          五、文件讀取操作

          讀取文件:==「read」== 頭文件: ?==「#include==

          「ssize_t read」(int fd , const void *buf , size_t count); ==「//從fd個(gè)文件讀取count個(gè)字節(jié)數(shù)據(jù)放到buf里」==

          返回值:若讀取成功,讀多少個(gè)字節(jié)返回多少個(gè)字節(jié),若讀到尾什么都沒讀到返回0,讀取失敗返回-1

          文件讀取示例代碼:

          #include
          #include
          #include
          #include
          #include
          #include

          int?main()
          {
          ???int?fd;
          ???char?*buf?="Refuel.CONG";
          ???fd=?open("./file",O_RDWR);
          ???printf("fd=%d\n",fd);
          ???if(fd?==?-1){
          ???????printf("open?file?failed\n");
          ???????fd?=?open("./file",?O_RDWR?|?O_CREAT?|?,0600);
          ???????if(fd>0){
          ????????????printf("create?file?success\n");
          ???????}
          ???}
          int?n_write?=?write(fd,buf,strlen(buf));
          if(n_write?!=?-1){
          ??????printf("write%d?byte?to?file\n",n_write);??//若讀取成功,返回讀到的??ite
          }
          char?*readBuf;
          readBuf?=?(char*)malloc(sizeof(char)*n_write+1);

          int?n_read?=?read(fd,reafBuf?,?n_write);
          printf("read=%d?,?context:%s\n",n_read,readBuf);
          close(fd);
          return?0;
          }

          結(jié)果什么都沒讀取到:是因?yàn)楣鈽?biāo)的原因,光標(biāo)在寫入數(shù)據(jù)后,光標(biāo)停在寫完的位置,讀取的時(shí)候光會(huì)變后面,什么也沒有所以讀取不到。

          ==「解決辦法:」==

          1. 把光標(biāo)移動(dòng)到頭。
          2. 重新打開文件。

          「重新打開文件的方式解決光標(biāo)的問題:」

          #include
          #include
          #include
          #include
          #include
          #include

          int?main()
          {
          ???int?fd;
          ???char?*buf?="Refuel.CONG";
          ???fd=?open("./file",O_RDWR);
          ???printf("fd=%d\n",fd);
          ???if(fd?==?-1){
          ???????printf("open?file?failed\n");
          ???????fd?=?open("./file",?O_RDWR?|?O_CREAT?|?,0600);
          ???????if(fd>0){
          ????????????printf("create?file?success\n");
          ???????}
          ???}
          int?n_write?=?write(fd,buf,strlen(buf));
          if(n_write?!=?-1){
          ??????printf("write%d?byte?to?file\n",n_write);??//若讀取成功,返回讀到的??ite
          }

          close(fd);????????????????????//寫完數(shù)據(jù)后關(guān)閉文件
          fd?=?open("./file",O_RDWR);????//重新打開

          char?*readBuf;
          readBuf?=?(char*)malloc(sizeof(char)*n_write+1);

          int?n_read?=?read(fd,reafBuf?,?n_write);
          printf("read=%d?,?context:%s\n",n_read,readBuf);
          close(fd);
          return?0;
          }

          結(jié)果為:

          六、文件光標(biāo)移動(dòng)操作

          光標(biāo)移動(dòng):==「lseek」== 頭文件:

          1. ==「#include==
          2. ==「#include==

          宏:

          1. ==「SEEK_SET」== ? ?「//指向文件的頭」
          2. ==「SEEK_CUR」== ? 「//指向當(dāng)前光標(biāo)位置」
          3. ==「SEEK_END」== ? 「//指向文件的尾」

          「off_t ?lseek」(int fd , off_t 「offset」 , int 「whence」); 作用:「將文件讀寫指針相對(duì) whence 移動(dòng) offset 個(gè)字節(jié)」參數(shù)說明:「(文件描述符,偏移值,固定的位置)」

          #include
          #include
          #include
          #include
          #include
          #include

          int?main()
          {
          ???int?fd;
          ???char?*buf?="Refuel.CONG";
          ???fd=?open("./file",O_RDWR);
          ???printf("fd=%d\n",fd);
          ???if(fd?==?-1){
          ???????printf("open?file?failed\n");
          ???????fd?=?open("./file",?O_RDWR?|?O_CREAT?|?,0600);
          ???????if(fd>0){
          ????????????printf("create?file?success\n");
          ???????}
          ???}
          int?n_write?=?write(fd,buf,strlen(buf));
          if(n_write?!=?-1){
          ??????printf("write%d?byte?to?file\n"n_write);?
          }
          char?*readBuf;
          readBuf?=?(char?*)malloc(sizeof?(char)*n_write+1);

          lseek?(fd,0,SEEK_SET);???//參數(shù):(文件描述,偏移值,固定的位置)
          //lseek(fd,-11?,SEEK_CUR);??//所在光標(biāo)位置往前偏移11個(gè)

          int?n_read?=?read(fd?,readBuf,n_write);
          printf("read=%d,context:%s\n",n_write,readBuf);
          close(fd);
          return?0;

          lseek (fd,0,SEEK_SET); ? //參數(shù):(文件描述,偏移值,固定的位置) lseek(fd,-11,SEEK_CUR); ?//所在光標(biāo)位置往前偏移11個(gè)

          七、文件操作原理簡述

          1.文件描述符:

          1. 對(duì)于內(nèi)核而言,所有打開文件都由文件描述符引用。文件描述符是一個(gè)非負(fù)整數(shù)。當(dāng)打開一個(gè)現(xiàn)存文件或者創(chuàng)建一個(gè)新文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符。當(dāng)讀寫一個(gè)文件時(shí),用open和creat返回的文件描述符標(biāo)識(shí)該文件,將其作為參數(shù)傳遞給read和write。按照慣例,UNIX shell 使用文件描述符0與進(jìn)程的標(biāo)準(zhǔn)輸入相結(jié)合,文件描述符1與標(biāo)準(zhǔn)輸出相結(jié)合,文件描述符2與標(biāo)準(zhǔn)錯(cuò)誤輸出相結(jié)合。STDIN_FILENO 、STDOUT_FILENO、STDERR_FILENO這幾個(gè)宏代替了0,1,2這幾個(gè)數(shù)。
          1. 文件描述符,這個(gè)數(shù)字在一個(gè)進(jìn)程中表示一個(gè)特定含義,當(dāng)我們open一個(gè)文件時(shí),操作系統(tǒng)在內(nèi)存中構(gòu)建了一些數(shù)據(jù)結(jié)構(gòu)來表示這個(gè)動(dòng)態(tài)文件,然后返回給應(yīng)用程序一個(gè)數(shù)字作為文件描述符,這個(gè)數(shù)字就和我們內(nèi)存中維護(hù)的這個(gè)動(dòng)態(tài)文件的這些數(shù)據(jù)結(jié)構(gòu)綁定上了,以后我們應(yīng)用程序如果要操作這個(gè)動(dòng)態(tài)文件,只需要用這個(gè)文件描述符區(qū)分。
          1. 文件描述符的作用域就是當(dāng)前進(jìn)程,除了這個(gè)進(jìn)程文件描述符就沒有意義了,open函數(shù)打開文件,打開成功返回一個(gè)文件描述符,打開失敗,返回-1。

          2.linux系統(tǒng)默認(rèn):

          標(biāo)準(zhǔn)描述符:「標(biāo)準(zhǔn)輸入(0) ?標(biāo)準(zhǔn)輸出(1) 標(biāo)準(zhǔn)錯(cuò)誤(3)」

          #include
          #include
          #include
          #include
          #include
          #include
          int?main(){
          ????int?fd;
          ????char?readBuf[128];
          ????
          ????int?n_read?=?read(0,readBuf,5);?????//?0?標(biāo)準(zhǔn)輸入
          ????int?n_write?=?write(1,readBuf,strlen(readBuf));?//?1?標(biāo)準(zhǔn)輸出
          ????printf("\n?end!\n");
          ????return?0;
          }
          在這里插入圖片描述

          3.操作文件時(shí)候:

          「打開/創(chuàng)建文件 ? ——> ? 讀取文件/寫入文件 ?——> ?關(guān)閉文件」==

          1、在Linux中要操作一個(gè)文件,一般是先open打開一個(gè)文件,得到文件描述符,然后對(duì)文件進(jìn)行讀寫操作(或其他操作),最后是close關(guān)閉文件即可。

          2、強(qiáng)調(diào)一點(diǎn):我們對(duì)文件進(jìn)行操作時(shí),一定要先打開文件,打開成功之后才能操作,如果打開失敗,就不用進(jìn)行后邊的操作了,「最后讀寫完成后,一定要關(guān)閉文件,否則會(huì)造成文件損壞?!?/strong>

          3、「文件平時(shí)是存放在塊設(shè)備中的文件系統(tǒng)文件中的,我們把這種文件叫靜態(tài)文件」,當(dāng)我們?nèi)pen打開一個(gè)文件時(shí),linux內(nèi)核做的操作包括:內(nèi)核在進(jìn)程中建立一個(gè)打開文件的數(shù)據(jù)結(jié)構(gòu),記錄下我們打開的這個(gè)文件;內(nèi)核在內(nèi)存中申請(qǐng)一段內(nèi)存,并且將靜態(tài)文件的內(nèi)容從塊設(shè)備中讀取到內(nèi)核中特定地址管理存放(叫動(dòng)態(tài)文件)。read write 都是對(duì)動(dòng)態(tài)文件進(jìn)行操作

          4、打開文件以后,以后對(duì)這個(gè)文件的讀寫操作,都是針對(duì)內(nèi)存中的這一份動(dòng)態(tài)文件的,而并不是針對(duì)靜態(tài)文件的。當(dāng)然我們對(duì)動(dòng)態(tài)文件進(jìn)行讀寫以后,此時(shí)內(nèi)存中動(dòng)態(tài)文件和快設(shè)備文件中的靜態(tài)文件就不同步了,當(dāng)我們close關(guān)閉動(dòng)態(tài)文件名,close內(nèi)部內(nèi)核將內(nèi)存中的動(dòng)態(tài)文件的內(nèi)容去更新(同步)塊設(shè)備中的靜態(tài)文件。

          5、為什么這么設(shè)計(jì),不直接對(duì)塊設(shè)備直接操作。「塊」(假設(shè)有100字節(jié))設(shè)備本身讀寫非常不靈活,是按塊讀寫的,最小只讀100字節(jié),而「內(nèi)存是擠字節(jié)單位操作的可而具可以隨機(jī)操作,很靈活」。

          「靜態(tài)文件」放入磁盤中的文件是靜態(tài)文件, 如:桌面上的文件.jpg

          「動(dòng)態(tài)文件」open靜態(tài)文件后,會(huì)在linux內(nèi)核產(chǎn)生結(jié)構(gòu)體記錄文件 ? 如:fd ? 信息節(jié)點(diǎn),buf(內(nèi)容,內(nèi)存)

          調(diào)用close時(shí)候,會(huì)把所有信息緩存到磁盤中

          八、文件操作編程小練習(xí)—實(shí)現(xiàn)cp指令代碼:

          ==「cp ( src.c ?//源文件 ,dest.c //復(fù)制到的目標(biāo)文件)」==

          「實(shí)現(xiàn)cp操作:」

          1.c語言參數(shù):./a.out ?_ _ ==2.實(shí)現(xiàn)思路:==

          1. 打開src.c
          2. 讀src到buf
          3. 創(chuàng)建/打開dest.c
          4. 將buf寫入dest.c
          5. close兩個(gè)文件

          ==c語言參數(shù):==「// 參數(shù)(argc是數(shù)組)(argv是二級(jí)指針是包含數(shù)組的數(shù)組:是argv里的每一項(xiàng)都是一個(gè)數(shù)組)」

          #include
          int?main(?int??argc?,?char?**agrv)????//?參數(shù)(argc是數(shù)組)(argv是包含數(shù)組的數(shù)組:是argv里的每一項(xiàng)都是一個(gè)數(shù)組)
          {
          ????printf("totol?params:%d\n",argc);
          ????printf("No.1??params:%d\n",argv[0]);
          ????printf("No.2??params:%d\n",argv[1]);
          ????printf("No.3??params:%d\n",argv[2]);?
          ???return?0;
          }

          輸入 :./a.out ? des ?src 結(jié)果:totol params : 3 No.1 ?params : ?./a.out No.2 ?params : ?des No.3 ?params : src

          「實(shí)現(xiàn)mycp操作代碼:」

          #include
          #include
          #include
          #include
          #include
          #include

          int?main(int?argc?,char?**argv){
          ????int?fdSrc;
          ????int?fdDest;
          ????char?*readBuf?=?NULL;
          ????if(argc?!=?3){
          ????????printf("param?error\n");
          ????????exit(-1);
          ????}
          ????
          fdSrc?=?open(argv[1],O_RDWR);??????//1.?打開fdSrc.c(源文件)
          int?size?=?lseek(fdSrc?,0,?SEEK_END);???//光標(biāo)記錄文件大小
          lseek(fdSrc?,?0,?SEEK_SET);???//?。∏f記得把?光標(biāo)回到頭
          readBuf?=?(char?*)malloc(sizeof(char)?*size+8);??//開辟readBuf空間大小

          int?n_read?=?read(fdSrc,readBuf,size);???//2.?讀取fdSrc(源文件)到readBuf緩沖區(qū)

          fdDest?=?open(argv[2],O_RDWR?|?O_CREAT?|?O_TRUNC?,0600);???//3.?打開/創(chuàng)建fdDest.c
          int?n_write?=?write(fdDest,readBuf,strlen(readBuf));??//4.?將readbuf寫入到fdDest.c

          close(fdSrc);????//5.關(guān)閉兩個(gè)文件
          close(fdDest);
          return?0;
          }

          mycp容易出現(xiàn)的小問題—實(shí)現(xiàn)優(yōu)化:

          1. 「用 lseek來光標(biāo)計(jì)算size數(shù)組」
          char?*readBuf?=?NULL;

          ?int?size?=?lseek(fdSrc,0,SEEK_END);
          ?????lseek(fdSrc?,?0?,SEEK_SET);
          ?????readBuf?=?(char?*)malloc(sizeof(char)*size?+?8);
          1. 「若要是拷貝大于1024的文件就不行」
          ?int?n_read?=?read(fdSrc,readBuf,size);????//讀取大小用lseek查出的大小.

          3.「目標(biāo)文件存在并且存在一些數(shù)據(jù),拷貝就會(huì)覆蓋了原來數(shù)據(jù)的一部分」

          解決方法:「O_TRUNC」 屬性去打開文件時(shí),如果這個(gè)文件中本來是有內(nèi)容的,而且為只讀或者只寫成功打開,則將其長度截?cái)酁?

          fdDes?=?open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);

          九、文件編程小應(yīng)用之修改程序的配置文件

          ==「(工作中常用)」== 配置文件的修改

          例如:SPEED=5 LENG=100 SCORE=90 LEVEL=95

          「修改指定內(nèi)容的思路:」

          1. 找到(要修改的)位置
          2. (修改的位置)往后移動(dòng)到(要改的值 )
            3. 修改要改的值

          找尋修改位置時(shí)候,用到 「strstr()」 函數(shù);功能:用來檢索子串在字符串中首次出現(xiàn)的位置

          「修改LENG的值 示例代碼:」

          #include
          #include
          #include
          #include
          #include
          #include
          #include

          int?main(int?argc?,?char?**argv){
          ???int?fdSrc;
          ???char?*readBuf=NULL;
          ???if(argc?!=?2?){
          ???????printf("pararm?error\n");
          ???????exit(-1);
          ???}
          ??fdSrc?=?open(argv[1],O_RDWR);
          ??int?size?=?lseek(fdSrc,0,SEEK_END);
          ??lseek?(fdSrc,0,SEEK_SET);
          ??
          ??readBuf?=(char?*)malloc(sizeof(char)*size+8);
          ??int?n_read=?read(fdSrc,readBuf,size);
          ??
          ??char?*p=strstr(readBuf,"LENG=");?//找到(要修改的)位置???
          ??//參數(shù)1?要找的源文件??2.“要找的字符串”
          ??if(p==NULL){
          ????printf("not?found\n");
          ????exit(-1);
          ??}
          ??p=p+strlen("LENG=");??//移動(dòng)字符串個(gè)字節(jié)
          ??*p='0';??????//*p??取內(nèi)容
          ??
          lseek?(fdSrc,0,SEEK_SET);
          int?n_write?=write(fdSrc,readBuf,strlen(readBuf));
          close(fdSrc);
          return?0;
          }

          「可以把封裝成一個(gè)函數(shù):」

          void?*changefile(int?fd,char?*readbuf,char*?f,char?t){
          ????????char?*p?=?strstr(readbuf,f);
          ????????if(p?==?NULL){
          ???????????printf("no?found\n");
          ???????????exit(-1);
          ????????}
          ????????p?=?p?+?strlen(f);
          ????????*p?=?t;
          ?????}

          int?main(int?argc,char?**argv)
          {
          ??????changefile(fdSrc,readBuf,"LENG=",'6');
          }

          十、寫一個(gè)整數(shù)到文件

          「ssize_t ?write」(int fd , const void *buf , size_t count);
          //將緩沖區(qū)buf指針指向內(nèi)存數(shù)據(jù),寫conut大小到fd.

          「ssize_t ?read」(int fd , const void *buf , size_t count);
          //從fd個(gè)文件讀取count個(gè)字節(jié)數(shù)據(jù)放到buf里

          1.寫入整型數(shù)代碼:

          #include
          #include
          #include
          #include
          #include
          #include
          #include

          int?main(){
          ???int?fd;
          ???int?data?=?100;
          ???int?data2?=?0;
          ???fd=open("./flie1",O_RDWR);
          ???
          ???int?n_write?=write(fd,?&data,?sizeof(int));
          ???lseek(fd,0,SEEK_SET);
          ???int?n_read?=read(fd,?&data2,?sizeof(int));

          ???printf("read?%d\n",data2);
          ???close(fd);
          ???return?0;
          }
          在這里插入圖片描述

          2.寫入結(jié)構(gòu)體代碼(1):

          struct?Test
          {

          ???int?a;
          ???char?c;
          };

          int?main(){
          ???int?fd;
          ???int?Test?data?=?{100,'a'};
          ???int?Test?data2?;
          ???fd=open("./flie1",O_RDWR);
          ???
          ???int?n_write?=write(fd,?&data,?sizeof(struct?Test));
          ???lseek(fd,0,SEEK_SET);
          ???int?n_read?=read(fd,?&data2,?sizeof(struct?Test));

          ???printf("read?%d?%s\n",data2.a,data2.c);
          ???close(fd);
          ???return?0;
          }

          3.寫入結(jié)構(gòu)體代碼(2):

          struct?Test
          {

          ???int?a;
          ???char?c;
          };

          int?main(){
          ???int?fd;
          ???int?Test?data[2]?=?{{100,'a'},{101,'b'}};
          ???int?Test?data2[2];
          ???fd=open("./flie1",O_RDWR);
          ???
          ???int?n_write?=write(fd,?&data,?sizeof(struct?Test)*2);
          ???lseek(fd,0,SEEK_SET);
          ???int?n_read?=read(fd,?&data2,?sizeof(struct?Test)*2);

          ???printf("read?%d?%s\n",data2[0].a,data2[0].c);
          ???printf("read?%d?%s\n",data2[1].a,data2[1].c);
          ???close(fd);
          ???return?0;
          }

          「注意寫入/讀入的 大小:」 ?sizeof(struct Test) 「乘2」

          「緩沖區(qū)可以寫入 :整數(shù),字符,結(jié)構(gòu)體等」

          十一、標(biāo)準(zhǔn)C庫對(duì)文件操作引入

          1. open 和 fopen 的區(qū)別

          「1.來源」

          • open是UNIX系統(tǒng)調(diào)用函數(shù),返回的是文件描述符,它是文件在文件描述符表里的索引。

          • fopen是ANSIC標(biāo)準(zhǔn)中的c語言庫函數(shù),在不同的系統(tǒng)中應(yīng)該調(diào)用不同的內(nèi)核API,返回值是一個(gè)指向文件結(jié)構(gòu)的指針。

          「2.移植性」

          這一點(diǎn)從上面的來源就可以推斷出來,fopen是C標(biāo)準(zhǔn)函數(shù),因此用有良好的移植性;而oprn是UNIX系統(tǒng)調(diào)用,移植性有限。如windows下相似的功能使用API函數(shù)。

          「3.適用范圍」

          open返回文件描述符,而文件描述符是UNIX系統(tǒng)下的一個(gè)重要概念,UNIX下的一切設(shè)備都是文件的形式操作,如網(wǎng)絡(luò)套件字,硬件設(shè)備(驅(qū)動(dòng))等。當(dāng)然包括操作普通正規(guī)文件。fopen是用來操縱普通正規(guī)文件的。

          「4.緩沖」

          1. 「緩沖文件系統(tǒng)」

            緩沖文件系統(tǒng)的特點(diǎn)是:在內(nèi)存開辟一個(gè)“緩沖區(qū)”,為程序中的每一個(gè)文件使用;當(dāng)執(zhí)行讀文件的操作時(shí),從磁盤文件將數(shù)據(jù)先讀入內(nèi)存“緩沖區(qū)”,裝滿后再從內(nèi)存“緩沖區(qū)”依此讀出需要的數(shù)據(jù)。執(zhí)行寫文件的操作時(shí),先將數(shù)據(jù)寫入內(nèi)存“緩沖區(qū)”,待內(nèi)存緩沖區(qū)”裝滿后再寫入文件。由此可以看出,內(nèi)存“緩沖區(qū)”的大小,影響著實(shí)際操作外存的次數(shù),內(nèi)存“緩沖區(qū)”越大,則操作外存的次數(shù)就少,執(zhí)行速度就快、效率高。一般來說,文件“緩沖區(qū)”的大小隨機(jī)器而定。fopen, fclose, fread, fwrite, fgetc, fgets. fputc, fputs, freopen, fseek. ftell, rewind等。

          2. 「非緩沖文件系統(tǒng)」

            緩沖文件系統(tǒng)是借助文件結(jié)構(gòu)體指針來對(duì)文件進(jìn)行管理,通過文件指針來對(duì)文件進(jìn)行訪問,既可以讀寫字符、字符電、格式化數(shù)據(jù),也可以讀寫二進(jìn)制數(shù)據(jù)。非緩沖文件系統(tǒng)依賴于操作系統(tǒng),通過操作系統(tǒng)的功能對(duì)文件進(jìn)行讀寫,是系統(tǒng)級(jí)的輸入輸出,它不設(shè)文件結(jié)構(gòu)體指針,只能讀寫二進(jìn)制文件,但效率高、速度快,由于ANSI標(biāo)準(zhǔn)不再包括非緩沖文件系統(tǒng),因此建議大家最好不要選擇它.open,close, read, write, getc, getchar, putc, putchar等。

            一句話總結(jié)一下,就是open無緩沖,fopen有緩沖。前者與read,write等配合使用,后者與freadfwrite等配合使用

            使用fopen函數(shù),由于在用戶態(tài)下就有了緩沖,因此進(jìn)行文件讀寫操作的時(shí)候就減少了用戶態(tài)和內(nèi)核態(tài)的切換(切換到內(nèi)核態(tài)調(diào)用還是需要調(diào)用系統(tǒng)調(diào)用API:read,write);而使用open函數(shù),在文件讀寫時(shí)則每次都需要進(jìn)行內(nèi)核態(tài)和用戶態(tài)的切換;表現(xiàn)為,如果順序訪問文件,fopen系列的函數(shù)要比直接調(diào)用open系列的函數(shù)快;如果隨機(jī)訪問文件則相反。這樣一總結(jié)梳理,相信大家對(duì)于兩個(gè)函數(shù)及系列函數(shù)有了一個(gè)更全面清晰的認(rèn)識(shí),也應(yīng)該知道在什么場合下使用什么樣的函數(shù)更合適 效率更高。

          2. fopen(); fwrite(); fread(); 方式寫入數(shù)據(jù)

          ==FILE ?*「fopen」 ?(const char *path ,const char *mode);==
          參數(shù)說明:path :路徑 ? mode ?:用什么方式打開 返回值:FILE 類型

          mode 打開模式:

          模式指令功能說明
          r只讀方式打開一個(gè)文本文件
          rb只讀方式打開一個(gè)二進(jìn)制文件
          w只寫方式打開一個(gè)文本文件
          wb只寫方式打開一個(gè)二進(jìn)制文件
          a追加方式打開一個(gè)文本文件
          ab追加方式打開一個(gè)二進(jìn)制文件
          r+可讀可寫方式打開一個(gè)文本文件
          rb+可讀可寫方式打開一個(gè)二進(jìn)制文件
          w+可讀可寫方式創(chuàng)建一個(gè)文本文件
          wb+讀可寫方式生成一個(gè)二進(jìn)制文件
          a+可讀可寫追加方式打開一個(gè)文本文件
          ab+可讀可寫方式追加一個(gè)二進(jìn)制文件

          「寫入:」==size_t ? 「fwrite」 ?(const void *ptr ?, size_t size ?, size_t nmemb ?, FILE *stream);==

          1. ptr ? ? 緩沖區(qū) 等同于(buf)

          2. size ?一個(gè)字符大?。╯izeof char) 3. nmemb ?個(gè)數(shù)
            4. stream (哪個(gè)文件) which file

          「讀?。骸?/strong>==size_t ?「fread」 ?(const void *ptr ,size_t size ,size_t nmemb ,FILE *stream);==

          「光標(biāo)問題:」==int ?「fseek」 ?(FILE *stream ?, long offset ,int whence);==

          「示例代碼:」

          #include
          #include

          int?main()
          {
          FILE?*fp;
          char?*str?=?"Refuel.CONG";
          char?readBuf[128]={0};

          fp?=?fopen("./CONG.txt","w+");???//可讀可寫方式創(chuàng)建一個(gè)文本文件?
          fwrite(str?sizeof(char),strlen(str),fp);
          //一次性寫一個(gè)char?寫str個(gè)字節(jié),到fp里
          fseek(fp,0,SEEK_SET);
          fread(readBuf,sizeof(char),strlen(str),fp);
          //從fp里?一次讀一個(gè)char?讀str個(gè)?讀到readBuf里去
          printf("read?data:%s\n",readBuf);
          fclose(fp);
          return?0;
          }

          也可改寫:fread (readBuf , ?sizeof(char) , ?* strlen(str) , 1 ?,fp);
          //讀*strlen(str)個(gè) ?讀 ?1 次

          3. n_read 和 n_write 的返回值

          「n_read 和 n_write 的返回值取決于第三個(gè)參數(shù)」==

          int?n_fwrite?=?fwrite(str?sizeof(char)*strlen(str),1,fp);
          int?n_fread?=?fread(str?sizeof(char)*strlen(str),1,fp);

          printf("read=%d,write=%d\n",n_read,n_write);

          結(jié)果:n_read= 1 n_write =1

          4. n_fread 和 n_fwrite 返回值區(qū)別

          ?int?n_fread?=?fread(str?sizeof(char)*strlen(str),100,fp);
          ?printf("n_read=%d\n",n_read);

          結(jié)果為 :n_read = 1

          「但是如果寫100結(jié)果就會(huì)不同」

          ?int?n_fwrite?=?fwrite(str?sizeof(char)*strlen(str),100,fp);
          ?printf("n_write=%d\n",n_write);

          結(jié)果為 :n_write= 100

          5. 標(biāo)準(zhǔn)c庫寫入結(jié)構(gòu)體到文件

          「fwrite()寫入結(jié)構(gòu)體代碼:」

          #include
          #include

          struct?Test
          {

          ????int??a;
          ????char?c;
          };
          int?main()
          {
          FILE?*fp;
          struct?Test?data1?={1100,'a'};
          struct?Test?data2;

          fp?=?fopen("./CONG.txt","w+");???//可讀可寫方式創(chuàng)建一個(gè)文本文件?
          int?n_fwrite?=?fwrite(&data?,?sizeof(stsuct?Test)?,1,?fp);

          fseek(fp,0,SEEK_SET);
          int?n_fread?=?fread(&data?,?sizeof(stsuct?Test)?,1,?fp);

          printf("read?=%d,%s\n",data2.a,data2.c);
          fclose(fp);
          return?0;
          }

          結(jié)果:read = 1100 , a

          6. fgetc(); ?fputc(); ?feof() 的使用方法;

          ==「讀字符函數(shù) :fgetc() 函數(shù)的用法」== 作用:從指定的文件中讀一個(gè)字符, 函數(shù)調(diào)用的形式為:char ch//字符變量 = fgetc(fp // 文件指針); 我們可以將讀取到的數(shù)據(jù)給到一個(gè)字符變量存儲(chǔ)。

          1. 「面對(duì)要讀取的數(shù)據(jù)繁多的情況,為了減少程序運(yùn)行的時(shí)間復(fù)雜度」,要用到 ==「fgets();」==
          2. 「fgets();」 ?功能是從指定的文件讀取一個(gè)字符串到字符數(shù)組中。函數(shù)的調(diào)用形式為:fgets(字符數(shù)組名,n,文件指針); 參數(shù):n 為一個(gè)正整數(shù)。表示從文件中讀出的字符串不超過n-1個(gè)字符,在讀入的最后一個(gè)字符后加上字符串結(jié)束標(biāo)志'0',說通俗易懂點(diǎn)就是讀多少?

          3. printf("%s\n",str);?//循環(huán)讀取所有數(shù)據(jù)?while(fgets(str?,100?,fp)){?
            //循環(huán)讀取所有數(shù)據(jù),直到fets讀到’\0‘
            ????printf("%s\n",str);?}?fclose(fp);?return?0?;?```

          ==「fputc() 函數(shù)的用法」==

          int fputc(int c , FILE *stream); 功能:把 c 寫入 文件stream里

          ==「feof() 函數(shù)的用法」==

          int ?feof (FILE *stream );作用:(「是否到尾巴的位置」):「測試在沒到達(dá)文件尾巴返回0,到達(dá)尾巴返回 非0」

          「feof() 函數(shù)使用代碼:」

          #include
          #include

          int?main(){
          ??FILE?*fp;
          ??int?i;
          ??char?c;
          ??fp?=?fopen("./test.txt",r);
          ??//沒到達(dá)文件尾巴返回0,到達(dá)尾巴返回非0
          ??while(!feof(fp)){??
          ??//沒到尾巴時(shí)返回0,取反?進(jìn)入while??當(dāng)?shù)竭_(dá)尾巴返回非0??取反=0?退出while
          ??????c=fgetc(fp);
          ??????printf("%c",c);
          ??}
          ??fclose(fp);
          ??return?0;
          }

          「fputc寫入文件代碼:」

          #include
          #include

          int?main(){
          ??FILE?*fp;
          ??int?i;
          ??char?*str?="Refuel.CONG";
          ??int?len?=?sizeof(str);

          ??fp?=?fopen("./test.txt","w+");
          ??if(fp?==??NULL){
          ????printf("打開文件出現(xiàn)錯(cuò)誤\n");
          ????exit(-1);
          ??}
          ??for(i=0;i?????fputc(*str,fp);
          ?????str++;
          ??}
          ??fclose(fp);
          ??return?0;
          }

          文件編程就到這里結(jié)束了!??!


          文件編程就到這里結(jié)束了?。?!

          原文鏈接 https://blog.csdn.net/weixin_44278698/article/details/123581754?utm_source=app&app_version=5.2.1&code=app_1562916241&uLinkId=usr1mkqgl919blen

          本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲??!

          推薦閱讀:

          為什么俄羅斯不怕芯片卡脖子?

          驚!初中生也來卷了……

          最近 Github 上爆火的 Chrome 生產(chǎn)力神器 Omni 是什么鬼?


          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。?/span>

          瀏覽 51
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    一级A黄片 | 无码免费在线视频 | 性爱免费视频毛片 | 伦中文亚洲 | 久久国产精品视频免费看 |