1. 程式人生 > >Linux C高階程式設計——檔案操作之庫函式

Linux C高階程式設計——檔案操作之庫函式

Linux C高階程式設計——檔案操作庫函式

宗旨:技術的學習是有限的,分享的精神是無限的

——為什麼要設計標準I/O庫?

直接使用API進行檔案訪問時,需要考慮許多細節問題

例如:read、write時,緩衝區的大小該如何確定,才能使效率最優

標準I/O庫封裝了諸多細節問題,包括緩衝區分配

——標準I/O庫緩衝

標準I/O庫提供緩衝的目的:儘可能減少使用read、write呼叫的次數,以提高I/O效率。

通過標準I/O庫進行的讀寫操作,資料都會被放置在標準I/O庫緩衝中中轉。

——緩衝型別

—全緩衝

在填滿標準I/O緩衝區後,才進行實際I/O操作(例如呼叫write函式)

呼叫fflush函式也能強制進行實際I/O操作

—行緩衝

在輸入和輸出遇到換行符時,標準I/O庫執行I/O操作

因為標準I/O庫用來收集每一行的快取的長度是固定的,所以,只要填滿了快取,即使沒有遇到新行符,也進行I/O操作

終端(例如標準輸入和標準輸出),使用行緩衝

—不帶緩衝

標準I/O庫不對字元進行緩衝儲存

標準出錯是不帶緩衝的,為了讓出錯資訊儘快顯示出來

——流的定向

對於ASCII字符集,一個字元用一個位元組表示

對於國際字符集,一個字元可用多個位元組表示

流的定向決定了所讀、寫的字元是單位元組還是多位元組的 

一、開啟關閉檔案

1fopen

——用於開啟一個指定的檔案

(1)函式原型

#include<stdio.h>
FILE* fopen(const char *restrict pathname, const char *restrict type);

(2)引數

        pathname:要開啟的檔名

        type:指定檔案的讀、寫方式

r/rb——只讀方式開啟

w/wb——只寫,不存在則建立,使檔案長度為0

a/ab——追加

r+/r+b/rb+——讀寫開啟

W+/w+b/wb+——使檔案長度為0,讀寫而開啟

a+/a+b/ab+——在檔案尾讀和寫而開啟或建立

(3)返回值

        ——FILE結構指標(open返回的是檔案描述符)

2fflush

——重新整理一個流(強制標準I/O庫進行系統呼叫,以將資料傳遞到核心)

(1)函式原型

int fflush(FILE *fp);

(2)函式引數

        fp:檔案指標;若fp=NULL,則重新整理所有輸出流

(3)返回值

        成功返回0,出錯返回EOF

3fclose

——關閉一個打開了的流

(1)函式原型

 int fclose(FILE *fp);

(2)函式引數和返回值

          fp:要關閉的流對應的檔案指標

(3)返回值

         —成功返回0,出錯返回EOF

         在該檔案被關閉之前,重新整理快取中的輸出資料。快取中的輸入資料被丟棄,如果標準I/O庫已經為該流自動分配了一個快取,則釋放此快取。

二、讀寫檔案流

1、字元讀/寫檔案流

1.1fgetc

——讀出流中的一個字元

(1)函式原型

int  fgetc(FILE *fp);

(2)函式引數

        fp:檔案指標

(3)返回值

        成功返回讀到的內容; 出錯返回-1。

1.2fputc

——寫一個字元到檔案流中

(1)函式原型

int  fputc(int c, FILE *fp);

(2)函式引數

        c:字元c

        fp:檔案指標

(3)返回值

        成功返回內容; 出錯返回-1

2、行讀寫檔案流(一行一行進行)——不能操作二進位制檔案

2.1fgets

——讀出流中的一行字串

(1)函式原型

char *fgets(char *s, int n, FILE *fp);

(2)函式引數

         s:字串指標,指向用來儲存所得資料的地址

         n:緩衝區大小

        fp:檔案指標

(3)返回值

        成功返回讀到的內容到s中; 出錯返回NULL。

2.2fputs

——寫一行字串到標準流中

(1)函式原型

int *fputs(char*s, FILE *fp);

(2)函式引數

        s:以空字元結尾的字串(後接換行符)寫入標準流stdout中

        fp:檔案指標

(3)返回值

        成功返回非負數; 出錯返回-1。

3、塊讀寫檔案流 (fread/fwrite)

——每次I/O操作讀寫某種數量的物件,而每個物件具有指定的長度

例如,可讀寫一個二進位制陣列、結構

(1)函式原型

size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);

(2)引數

        第一個引數ptr:用於讀寫的緩衝區

        第二個引數size:每個物件的大小

        第三個引數nobj:要讀寫的物件個數

        第四個引數fp:檔案指標

(3)返回值

        返回實際讀/寫的物件數

三、檔案流定位

1、ftell

——用於獲取當前檔案偏移量

(1)函式原型

long ftell(FILE *fp);

(2)函式引數

         fp:檔案指標

(3)返回值

        成功返回當前檔案偏移量; 出錯返回-1。

2、fseek

——用於設定當前檔案偏移量

(1)函式原型:

int fseek(FILE *fp, long offset, int whence);

(2)函式引數

        第一個引數fp:檔案指標

        第二個引數offset:相對偏移量:需結合whence才能計算出真正的偏移量

        第三個引數whence:該引數取值是三個常量

SEEK_SET: 當前檔案偏移量為:距檔案開始處的offset個位元組  

SEEK_CUR: 當前檔案偏移量為:當前檔案偏移量+offset(可正可負)                       

SEEK_END: 當前檔案偏移量為:當前檔案長度+offset(可正可負)  

(3)返回值

        成功返回0,出錯返回非0     

3、rewind                                  

—— 用於將檔案偏移量設定到檔案的起始位置    

(1)函式原型

void rewind(FILE *fp);

(2)函式引數

        fp:檔案指標 

(3)返回值

// 小程式:用標準庫函式實現檔案拷貝功能:
#include<stdio.h>
//#include<string.h>
#include<stdlib.h>

void file_copy(char *fd, char *fp);

int main(intargc, char **argv)
{
  file_copy(argv[1], argv[2]);

  return 0;
}

void file_copy(char *fd, char *fp)
{
  FILE *from_fd, *to_fd;
  int ret, file_len; //定義檔案大小
  char buffer[1024];//緩衝區

  if((from_fd = fopen(fd, "rb")) == NULL) //開啟目標檔案
  {
    printf("file openfail!\n");
    exit(1);
  }
  if((to_fd = fopen(fp, "wb")) == NULL) //建立新檔案
  {
    printf("file openfail!\n");
    exit(0);
  }
  fseek(from_fd, 0L, SEEK_END);
  file_len = ftell(from_fd);//計算檔案大小
  fseek(from_fd, 0L, SEEK_SET);

  if((ret = fread(buffer, file_len, 1, from_fd)) == -1) //讀取檔案到buffer中,返回實際讀到的物件個數(不是讀取的位元組數)
  {
    printf("file readfail!\n");
    exit(0);
  }
  //printf("!!!!!!!!!!!%d\n",ret);

  fwrite(buffer, file_len, 1, to_fd); //把buffer裡面的內容寫到新檔案中

  fclose(from_fd);
  fclose(to_fd);//關閉檔案
}