【APUE】文件 I/O 操作

      網友投稿 685 2025-03-31

      博客地址 :?http://blog.csdn.net/shulianghan/article/details/46980271


      一. 文件打開關閉操作相關函數介紹

      1. open 函數

      (1) open 函數簡介

      open 函數解析 :

      -- 函數定義 :

      #include

      int

      open(const char *path, int oflag, ...);

      -- 返回值 : 打開文件成功, 返回文件描述符; 如果失敗, 返回 -1; 返回的文件描述符是最小的未用描述符值

      (2) open 函數參數簡介

      參數解析 :

      --?const char *path : 要打開或者創建的文件名;

      --?int oflag : 函數選項, 可以是多個常量進行 "或" 運算;

      -- 第三參數 : 對于打開文件來說是用不到第三參數的, 如果需要創建文件, 則需要指定第三參數;

      int oflag 參數必選常量解析 : 下面的三個常量必須只能且只能指定一個;

      -- O_RDONLY : 打開的文件只能讀取, 沒有寫權限;

      -- O_WRONLY : 打開的文件只能寫入, 沒有讀權限;

      -- O_RDWR : 打開的文件既能讀取, 也能寫入, 有雙權限;

      int oflag 參數可選常量解析 :

      -- O_APPEND : 每次寫入都追加到文件末尾;

      -- O_CREATE : 如果文件不存在, 就創建, 如果有這個參數, 就需要使用第三個參數來指定創建文件時的參數;

      -- O_EXCL : 指定該參數, 同時指定 O_CREATE, 文件如果存在就會報錯;

      -- O_TRUNC : 如果文件存在, 并且有寫權限的前提下, 打開時會將其內容清空, 從新寫入;

      -- O_NOCTTY : 如果第一個參數文件路徑指向一個終端設備, 不能將該設備作為進程的控制終端;

      -- O_NONBLOCK : 如果文件路徑指向一個 FIFO, 特殊文件塊, 字符特殊文件, 同時指定該選項, 文件的IO操作設置為非阻塞模式;

      int oflag 同步參數可選常量解析?:

      -- O_DSYNC : 每次 write 操作之前等待 IO 完成, 如果寫操作不影響讀取剛寫入的數據, 則不等待文件屬性被更新;

      -- O_RSYNC : 讀操作時等待, 直到所有的寫操作都完成;

      -- O_SYNC : 每次寫都要等待物理 IO 操作完成, 包括 write 引起的文件屬性更新; 即 數據和屬性同步更新;

      2. create 函數

      (1) create 函數簡介

      create 函數簡介 :

      -- 函數定義 :

      #include

      int

      creat(const char *path, mode_t mode);

      -- 等效函數 : open(path_name, O_WRONLY | O_CREATE | O_TRUNC, mode);

      -- mode_t mode 參數 : 指定文件的所有者;

      (2) create 函數局限性

      create 局限性 :

      -- 只寫 : create 函數只能以只寫方式打開創建的文件;

      -- 讀取新文件方法 : 先 create 創建只寫文件, 再調用 close 函數, 再調用 open 方法打開文件讀取文件;

      -- 創建只讀文件 : open(path_name, O_RDWR | O_CREATE | O_TRUNC, mode);

      3. close 函數

      函數簡介 :

      -- 函數定義 :

      #include

      int

      close(int fildes);

      -- 關于進程 : 進程終止時, 內核會自動關閉該進程中打開的所有文件, 很多情況下都會使用關閉進程隱式關閉文件;

      二. 文件偏移操作相關函數介紹

      1. lseek 函數

      (1) lseek 函數簡介

      lseek 函數簡介 :

      -- 函數定義 :

      #include

      off_t

      lseek(int fildes, off_t offset, int whence);

      -- 作用 : 顯式的為一個打開的文件設置偏移量;

      -- 返回值 : 如果設置偏移量成功, 返回新的偏移量;

      (2) 文件偏移量簡介

      文件偏移量 :

      -- 默認偏移量 : 打開一個文件時默認 當前文件偏移量 是0, 除非指定 O_APPEND 選項;

      -- 偏移量的值 : 普通文件偏移量必須是非負整數; 對于某些設備文件允許存在負數偏移量, 因此判斷是否可 lseek 時, 要判斷返回的文件偏移量是否 == -1;

      (3) int where 參數簡介

      where 參數簡介 :

      -- SEEK_SET : 將文件偏移量設置為 0 + offset;

      -- SEEK_CUR : 將文件偏移量設置為 當前位移 + offset;

      -- SEEK_END : 將文件偏移量設置為 文件長度 + offset;

      (4) lseek 源碼示例

      源碼示例 :

      /*************************************************************************

      > File Name: fun_lseek.c

      > Author: octopus

      > Mail: octopus_truth.163.com

      > Created Time: 三 7/22 07:46:59 2015

      ************************************************************************/

      #include

      #include

      #include

      int main(int argc, char * argv[])

      {

      /*

      * 設置標準輸入文件的 "當前文件偏移量",

      * 設置為當前的位置 + 0;

      */

      if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)

      printf("lseek 結果 -1, 該文件不能lseek\n");

      【APUE】文件 I/O 操作

      else

      printf("該文件可以執行 lseek 方法\n");

      exit(0);

      }

      localhost:file octopus$ gcc fun_lseek.c

      localhost:file octopus$ ./a.out

      該文件可以執行 lseek 方法

      (5) 文件空洞

      文件空洞形成 :

      -- 文件偏移量作用 : 文件偏移量是記錄在內核中, 不引起 IO 操作, 這個偏移量主要用于執行下一次的 IO 操作;

      -- 空洞形成 : 如果文件偏移量大于當前文件長度, 下一次寫操作會直接加長文件, 并在中間形成一個 "文件空洞";

      -- 磁盤占用情況 : 文件空洞是不占用磁盤存儲區的, 寫入數據超出文件長度時, 新寫入的數據會重新分配磁盤塊, 之間的一段文件空洞不會占用磁盤空間;

      三. 文件讀寫操作相關函數介紹

      1. read 函數

      函數簡介 :

      -- 函數內容 :

      #include

      #include

      #include

      ssize_t

      read(int fildes, void *buf, size_t nbyte);

      -- 返回值 : 如果 read 操作成功, 返回讀取到得字節數, 如果失敗, 返回 -1;

      2. write 函數

      函數簡介 :

      -- 函數內容 :

      #include

      ssize_t

      write(int fildes, const void *buf, size_t nbyte);

      -- 函數作用 : 將 buf 字符串的前 nbyte 個字節數據寫入 files 文件標示符 代表的文件中;

      -- 返回值 : 若成功, 返回已寫的字節數, 如果失敗返回 -1;

      3. write read 函數示例

      源碼示例 :

      -- 源碼 :

      /*************************************************************************

      > File Name: fun_read_write.c

      > Author: Han Shuliang

      > Mail: octopus_truth@163.com

      > Created Time: 五 7/29 15:00:18 2016

      ************************************************************************/

      #include

      #include

      #define SIZE 1024

      int main(int argc, char * argv[])

      {

      int n;

      char buf[SIZE];

      //讀取標準輸入流中的數據到 buf 字節數組中

      while ((n = read(STDIN_FILENO, buf, SIZE)) > 0)

      //將 buf 字節數組中的數據寫出到 標準輸出流中

      if(write(STDOUT_FILENO, buf, n)!= n)

      printf("寫出內容出錯");

      if(n < 0)

      printf("讀取過程出錯");

      return 0;

      }

      -- 執行結果 :

      bogon:file octopus$ gcc fun_read_write.c

      bogon:file octopus$ ./a.out

      Han Shuliang

      Han Shuliang

      CSDN

      CSDN

      ^C

      bogon:file octopus$

      4. 函數綜合示例

      /*************************************************************************

      > File Name: fun_read.c

      > Author: octopus

      > Mail: octopus_truth.163.com

      > Created Time: 一 7/27 07:09:36 2015

      ************************************************************************/

      #include

      #include // ... read() 頭文件

      #include // ... read() 頭文件

      #include // ... read() write() 函數頭文件

      #include // va_list 可變參數操作頭文件

      #include // strlen strcat 方法的頭文件

      #include // errno 的頭文件

      #include // exit() 方法的頭文件

      #include // open() 函數的頭文件

      #define MAXLINE 4096

      #define MAXWORD 20

      void err_sys(const char *fmt, ...);

      int main(int argc, char * argv[])

      {

      char *buf = "abcdefg\n";

      char buf_read[MAXWORD];

      int fd;

      int creat_result;

      int write_size;

      int close_result;

      int read_size;

      //創建一個文件, 使用打開方式, 如果文件不存在, 就重創建并打開

      if( ( fd = open("file_read_write.file", O_WRONLY | O_CREAT | O_TRUNC) ) == -1)

      err_sys("創建文件出錯");

      //向文件中寫出數據

      if( (write_size = write(fd, buf, strlen(buf))) == -1)

      err_sys("向文件寫出數據出錯");

      if( (close_result = close(fd)) == -1)

      err_sys("關閉文件出錯");

      if( (fd = open("file_read_write.file", O_RDONLY)) == -1)

      err_sys("打開文件出錯");

      //從文件中讀取文件內容

      if( (read_size = read(fd, buf_read, strlen(buf)) ) == -1)

      err_sys("讀取文件出錯");

      if( (close_result = close(fd)) == -1)

      err_sys("關閉文件出錯");

      printf("文件中得內容 : %s \n", buf_read);

      }

      static void err_doit(int errnoflag, int error, const char* fmt, va_list ap)

      {

      char buf[MAXLINE];

      //將 ap 可變參數使用 fmt 格式, 放置 MAXLINE 個字符到 buf 緩沖中

      vsnprintf(buf, MAXLINE, fmt, ap);

      /*

      * 如果需要錯誤信息, 根據錯誤號獲取標準錯誤信息, 將該信息添加到 buf 緩沖中

      * strlen 作用 : 獲取字符串長度

      * strerror 作用 : 根據錯誤號獲取錯誤信息

      */

      if(errnoflag)

      snprintf(buf + strlen(buf), MAXLINE - strlen(buf), ": %s", strerror(errno));

      //在 buf 字符串后添加換行符號

      strcat(buf, "\n");

      //刷新標準輸出流

      fflush(stdout);

      //將標準錯誤輸出添加到 buf 緩沖區

      fputs(buf, stderr);

      //刷新所有緩沖區

      fflush(NULL);

      }

      void err_sys(const char *fmt, ...)

      {

      va_list ap;

      va_start(ap, fmt);

      err_doit(1, errno, fmt, ap);

      va_end(ap);

      exit(0);

      }

      octopus-2:file octopus$ ls

      fun_lseek.c fun_lseek_hole.c fun_read_write.c

      octopus-2:file octopus$ gcc fun_read_write.c

      octopus-2:file octopus$ sudo ./a.out

      Password:

      文件中得內容 : abcdefg

      octopus-2:file octopus$ ls

      a.out file_read_write.file fun_lseek.c fun_lseek_hole.c fun_read_write.c

      octopus-2:file octopus$

      四. 文件讀寫原子操作相關函數介紹

      1. pread 函數

      pread 函數 :

      -- 1. 函數內容 :

      #include

      ssize_t pread(int fd, void *buf, size_t count, off_t offset);

      -- 2. 函數作用 : 讀取文件描述符 fd 對應的文件, 返回讀取到的文件字節個數, 讀取到文件結尾 返回 0, 出現錯誤返回 -1;

      -- 3. 函數返回值 : 返回讀取文件的字節數, 讀取到結尾返回 0, 出錯返回 -1;

      pread 與 read 方法作用 :

      -- 1. 等價執行流程 : pread 方法等價于 先調用?lseek 方法, ?再調用?read 方法;

      -- 2. 與等價流程的區別 : ① 執行 pread 方法時, 先定位 后 讀取 的兩個操作, 不能中斷; ② 文件指針 不更新;

      2. pwrite?函數

      pwrite?函數 :

      -- 1. 函數內容 :

      #include

      ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

      -- 2. 函數作用 : 寫出數據到指定的位置;

      -- 3. 函數返回值 : 返回寫出的字節數, 出現錯誤返回 -1;

      -- 4. 等價操作 : pwrite 等價于 lseek 和 write 操作;

      3. pread 和 pwrite 函數示例

      函數示例過程 :

      -- 1. 打開文件, 如果沒有就創建;

      -- 2. 寫出 a ~ z 26個子母;

      -- 3. 讀取文件?10 ~ 15 個字節;

      -- 4. 向第 10 個字節處寫出 "00000" 字符串;

      函數示例 :

      -- 代碼 :

      #include

      #include

      #include

      #include

      int main(int argc, char **argv)

      {

      printf("main : \n");

      int file_fd, write_result;

      char * buffer = "abcdefghigklmnopqrstuvwxyz";

      file_fd = open("5.pread_write.txt", O_RDWR | O_APPEND | O_CREAT);

      printf("file_fd = %d\n", file_fd);

      write_result = write(file_fd, buffer, strlen(buffer));

      printf("write success, count = %d\n", write_result);

      return 0;

      }

      .

      .

      .

      .

      .

      .

      博客地址 :?http://blog.csdn.net/shulianghan/article/details/46980271

      任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel如何設置身份證號碼格式 六種方法快速解決身份證產生亂碼
      下一篇:Redis 的 8 大數據類型,寫得非常好!(redis的五種數據類型)
      相關文章
      男人的天堂av亚洲一区2区| 亚洲日本va中文字幕久久| 久久精品国产亚洲沈樵| 亚洲国产日韩成人综合天堂 | mm1313亚洲国产精品无码试看| 亚洲一区二区三区不卡在线播放| 亚洲第一页在线视频| 亚洲AV无码久久精品蜜桃| 亚洲精品无码久久千人斩| 亚洲三区在线观看无套内射| 精品国产亚洲男女在线线电影| 亚洲另类激情专区小说图片| 亚洲男人的天堂一区二区| 日韩亚洲人成在线综合| 亚洲AⅤ视频一区二区三区 | 蜜芽亚洲av无码精品色午夜| 老色鬼久久亚洲AV综合| 亚洲最大黄色网站| 亚洲人成免费网站| 色在线亚洲视频www| 亚洲人成网站色7799| 成人婷婷网色偷偷亚洲男人的天堂| 久久无码av亚洲精品色午夜| 亚洲精品色婷婷在线影院| 久久久久国产亚洲AV麻豆| 亚洲国产一二三精品无码| 亚洲电影国产一区| 亚洲女人初试黑人巨高清| 99热亚洲色精品国产88| 亚洲国产精品无码久久| 亚洲精品NV久久久久久久久久| 国产亚洲色视频在线| 久久久久亚洲AV片无码| 亚洲国产精品久久丫| 亚洲成_人网站图片| 国产亚洲视频在线观看网址| 亚洲永久无码3D动漫一区| 亚洲第一区香蕉_国产a| 亚洲人成影院午夜网站| 亚洲熟女www一区二区三区| 亚洲AV无码成H人在线观看|