天天看點

C語言 檔案操作相關函數

文章目錄

  • ​​頭檔案:stdio.h​​
  • ​​檔案打開關閉函數​​
  • 檔案打開(fopen)
  • 參數mode可選值
  • 案例
  • 檔案關閉(fclose)
  • ​​檔案讀寫相關函數​​
  • 總覽
  • 字元讀寫函數
  • 字元讀寫案例
  • 行讀寫函數
  • 行讀寫案例
  • 塊讀寫函數
  • 塊讀寫案例
  • 格式化讀寫函數
  • 格式化讀寫案例
  • 随機讀寫函數
  • 随機讀寫案例
  • ​​檔案操作綜合案例​​

頭檔案:stdio.h

#include <stdio.h> 
      

檔案打開關閉函數

檔案的打開操作表示将給使用者指定的檔案在記憶體配置設定一個​

​FILE結構區​

​,并将該結構的指針傳回給使用者程式,以後使用者程式就可用此​

​FILE指針​

​來實作對指定檔案的存取操作了。當使用打開函數時,必須給出檔案名、檔案操作方式(讀、寫或讀寫)。

FILE * fopen(const char * filename, const char * mode);
      
  • 功能:打開檔案
  • 參數:

    ​filename​

    ​:需要打開的檔案名,根據需要加上路徑

    ​mode​

    ​:打開檔案的權限設定
  • 傳回值:

    成功:檔案指針

    失敗:NULL

方式 含義

​“r”​

打開,隻讀,檔案必須已經存在。

​“w”​

隻寫,如果檔案不存在則建立,如果檔案已存在則把檔案長度截斷(Truncate)為0位元組。再重新寫,也就是替換掉原來的檔案内容檔案指針指到頭。

​“a”​

隻能在檔案末尾追加資料,如果檔案不存在則建立

​“rb”​

打開一個二進制檔案,隻讀

​“wb”​

打開一個二進制檔案,隻寫

​“ab"​

打開一個二進制檔案,追加

​“r+”​

允許讀和寫,檔案必須已存在

​“w+”​

允許讀和寫,如果檔案不存在則建立,如果檔案已存在則把檔案長度截斷為0位元組再重新寫 。

​“a+”​

允許讀和追加資料,如果檔案不存在則建立

​“rb+”​

以讀/寫方式打開一個二進制檔案

​“wb+”​

以讀/寫方式建立一個新的二進制檔案

​“ab+”​

以讀/寫方式打開一個二進制檔案進行追加

檢查fopen的傳回值:

如何函數失敗,它會傳回一個NULL值。如果程式不檢查錯誤,這個NULL指針就會傳給後續的I/O函數。它們将對這個指針執行間接通路,并将失敗

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

FILE *fp = NULL;

// "\\"這樣的路徑形式,隻能在windows使用
// "/"這樣的路徑形式,windows和linux平台下都可用,建議使用這種
// 路徑可以是相對路徑,也可是絕對路徑
fp = fopen("../test", "w");
//fp = fopen("..\\test", "w");

if (fp == NULL) //傳回空,說明打開失敗
  {
//perror()是标準出錯列印函數,能列印調用庫函數出錯原因
perror("open");
return;
  }
}

int main()
{
test();
return 0;
}
      
C語言 檔案操作相關函數

檔案操作完成後,如果程式沒有結束,必須要用​

​fclose()函數​

​進行關閉,這是因為對打開的檔案進行寫入時,若檔案緩沖區的空間未被寫入的内容填滿,這些内容不會寫到打開的檔案中。隻有對打開的檔案進行關閉操作時,停留在檔案緩沖區的内容才能寫到該檔案中去,進而使檔案完整。再者一旦關閉了檔案,該檔案對應的​

​FILE結構​

​将被釋放,進而使關閉的檔案得到保護,因為這時對該檔案的存取操作将不會進行。檔案的關閉也意味着釋放了該檔案的緩沖區。

int fclose(FILE * stream);
      
  • 功能:關閉先前​

    ​fopen()​

    ​打開的檔案。此動作讓緩沖區的資料寫入檔案中,并釋放系統所提供的檔案資源。
  • ​stream​

    ​:檔案指針
  • 成功:0

    失敗:-1

它表示該函數将關閉FILE指針對應的檔案,并傳回一個整數值。若成功地關閉了檔案,則傳回一個0值,否則傳回一個非0值.

檔案讀寫相關函數

檔案讀寫相關基本函數包括以下幾個方面:

  • 按照字元讀寫檔案:fgetc(), fputc()
  • 按照行讀寫檔案:fputs(), fgets()
  • 按照塊讀寫檔案:fread(), fwirte()
  • 按照格式化讀寫檔案:fprintf(), fscanf()
  • 按照随機位置讀寫檔案:fseek(), ftell(), rewind()

int fputc(int ch, FILE * stream);
      
  • 功能:将​

    ​ch​

    ​轉換為​

    ​unsigned char​

    ​後寫入stream指定的檔案中
  • ​ch​

    ​:需要寫入檔案的字元

    ​stream​

  • 成功:成功寫入檔案的字元

    失敗:傳回-1

int fgetc(FILE * stream);
      
  • 功能:從stream指定的檔案中讀取一個字元
  • ​stream​

  • 成功:傳回讀取到的字元
int feof(FILE * stream);
      
  • 功能:檢測是否讀取到了檔案結尾
  • ​stream​

  • 非0值:已經到檔案結尾

    0:沒有到檔案結尾

将把流指針fp指向的檔案中的一個字元讀出,并賦給ch,當執行​

​fgetc()函數​

​時,若當時檔案指針指到檔案尾,即遇到檔案結束标志​

​EOF(其對應值為-1)​

​,該函數傳回一個 -1 給ch,在程式中常用檢查該函數傳回值是否為 -1 來判斷是否已讀到檔案尾,進而決定是否繼續。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

//寫檔案
FILE* fp_write = NULL;
//寫方式打開檔案
fp_write = fopen("./mydata.txt", "w+");
if (fp_write == NULL) {
return;
  }

char buf[] = "this is a test for pfutc!";
for (int i = 0; i < strlen(buf); i++) {
fputc(buf[i], fp_write);
  }

fclose(fp_write);

//讀檔案
FILE* fp_read = NULL;
fp_read = fopen("./mydata.txt", "r");
if (fp_read == NULL) {
return;
  }

#if 1
//判斷檔案結尾 注意:多輸出一個空格
while (!feof(fp_read)) {
printf("%c", fgetc(fp_read));
  }
#else
char ch;
while ((ch = fgetc(fp_read)) != EOF) {
printf("%c", ch);
  }
#endif
}

int main()
{
test();
return 0;
}
      

輸出結果為:

C語言 檔案操作相關函數

int fputs(const char * str, FILE * stream);
      
  • 功能:将str所指定的字元串寫入到stream指定的檔案中, 字元串結束符 ‘\0’ 不寫入檔案。
  • ​str​

    ​:字元串

    ​stream​

char * fgets(char * str, int size, FILE * stream);
      
  • 功能:從stream指定的檔案内讀入字元,儲存到str所指定的記憶體空間,直到出現換行字元、讀到檔案結尾或是已讀了size - 1個字元為止,最後會自動加上字元 ‘\0’ 作為字元串結束。
  • ​str​

    ​size​

    ​:指定最大讀取字元串的長度(size - 1)

    ​stream​

  • 成功:成功讀取的字元串

    讀到檔案尾或出錯: NULL

往檔案中寫入四行,并讀出輸出。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

//寫檔案
FILE* fp_write = NULL;
//寫方式打開檔案
fp_write = fopen("./mydata.txt", "w+");
if (fp_write == NULL) {
perror("fopen:");
return;
  }

char* buf[] = {
"01 倩 this is a test for pfutc!\n",
"02 倩 this is a test for pfutc!\n",
"03 倩 this is a test for pfutc!\n",
"04 倩 this is a test for pfutc!\n",
  };
for (int i = 0; i < 4; i++) {
fputs(buf[i], fp_write);
  }

fclose(fp_write);

//讀檔案
FILE* fp_read = NULL;
fp_read = fopen("./mydata.txt", "r");
if (fp_read == NULL) {
perror("fopen:");
return;
  }

//判斷檔案結尾
while (!feof(fp_read)) {
char temp[1024] = { 0 };
fgets(temp, 1024, fp_read);
printf("%s", temp);
  }

fclose(fp_read);
}


int main()
{
test();
return 0;
}
      

運作結果為:

C語言 檔案操作相關函數

size_t fwrite(
const void *ptr, 
size_t size, 
size_t nmemb, 
FILE *stream
);
      
  • 功能:以資料塊的方式給檔案寫入内容
  • ​ptr​

    ​:準備寫入檔案資料的位址

    ​size​

    ​: ​

    ​size_t​

    ​ 為 ​

    ​unsigned int類型​

    ​,此參數指定寫入檔案内容的塊資料大小

    ​nmemb​

    ​:寫入檔案的塊數,寫入檔案資料總大小為:​

    ​size * nmemb​

    stream

    :已經打開的檔案指針
  • 成功:實際成功寫入檔案資料的塊數,此值和​

    ​nmemb​

    ​相等

    失敗:0

size_t fread(
void *ptr, 
size_t size, 
size_t nmemb, 
FILE *stream
);
      
  • 功能:以資料塊的方式從檔案中讀取内容
  • ​ptr​

    ​:存放讀取出來資料的記憶體空間

    ​size​

    ​size_t​

    ​unsigned int類型​

    ​,此參數指定讀取檔案内容的塊資料大小

    ​nmemb​

    ​:讀取檔案的塊數,讀取檔案資料總大小為:​

    ​size * nmemb​

    stream

  • 成功:實際成功讀取到内容的塊數,如果此值比​

    ​nmemb​

    ​小,但大于0,說明讀到檔案的結尾。

建立教師結構體,寫入老師資訊,并從檔案中讀取資訊輸出:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

// 老師結構體
typedef struct _TEACHER {
char name[64];
int age;
}Teacher;

void test() {
//寫檔案
FILE* fp_write = NULL;
//寫方式打開檔案
fp_write = fopen("./mydata.txt", "wb");
if (fp_write == NULL) {
perror("fopen:");
return;
  }

Teacher teachers[4] = {
    { "倩", 33 },
    { "利", 28 },
    { "Jos", 45},
    { "咪咪", 35}
  };

for (int i = 0; i < 4; i++) {
fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
  }
//關閉檔案
fclose(fp_write);

//讀檔案
FILE* fp_read = NULL;
fp_read = fopen("./mydata.txt", "rb");
if (fp_read == NULL) {
perror("fopen:");
return;
  }

Teacher temps[4];
fread(&temps, sizeof(Teacher), 4, fp_read);
printf("輸出老師們的資訊:\n");
for (int i = 0; i < 4; i++) {
printf("姓名:%s  年齡:%d\n", temps[i].name, temps[i].age);
  }

fclose(fp_read);
}


int main()
{
test();
return 0;
}
      
C語言 檔案操作相關函數

int fprintf(FILE * stream, const char * format, ...);
      
  • 功能:根據參數​

    ​format​

    ​字元串來轉換并格式化資料,然後将結果輸出到stream指定的檔案中,指定出現字元串結束符​

    ​'\0'​

    ​為止。
  • ​stream​

    ​:已經打開的檔案

    ​format​

    ​:字元串格式,用法和​

    ​printf()​

    ​一樣
  • 成功:實際寫入檔案的字元個數
int fscanf(FILE * stream, const char * format, ...);
      
  • 功能:從​

    ​stream​

    ​指定的檔案讀取字元串,并根據參數​

    ​format​

    ​字元串來轉換并格式化資料。
  • ​stream​

    ​format​

    ​scanf()​

  • 成功:實際從檔案中讀取的字元個數

    失敗: - 1

注意:fscanf遇到空格和換行時結束。

寫入一行帶空格的字元串,讀取輸出:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

//寫檔案
FILE* fp_write = NULL;
//寫方式打開檔案
fp_write = fopen("./mydata.txt", "w");
if (fp_write == NULL) {
perror("fopen:");
return;
  }

fprintf(fp_write, "he llo wor ld :%d!", 99999);

//關閉檔案
fclose(fp_write);

//讀檔案
FILE* fp_read = NULL;
fp_read = fopen("./mydata.txt", "rb");
if (fp_read == NULL) {
perror("fopen:");
return;
  }

char temps[1024] = { 0 };
while (!feof(fp_read)) {
fscanf(fp_read, "%s", temps);
printf("%s", temps);
  }

fclose(fp_read);
}

int main()
{
test();
return 0;
}
      
C語言 檔案操作相關函數

注意:這裡的随機讀寫,不是系統随機位置就真随意讀寫了,是你要指定的随意位置進行讀寫

int fseek(FILE *stream, long offset, int whence);
      
  • 功能:移動檔案流(檔案光标)的讀寫位置。
  • ​stream​

    ​:已經打開的檔案指針

    ​offset​

    ​:根據​

    ​whence​

    ​來移動的位移數(偏移量),可以是正數,也可以負數,如果正數,則相對于​

    ​whence​

    ​往右移動,如果是負數,則相對于​

    ​whence​

    ​往左移動。如果向前移動的位元組數超過了檔案開頭則出錯傳回,如果向後移動的位元組數超過了 檔案末尾,再次寫入時将增大檔案尺寸。

    ​whence​

    ​:其取值如下:
  • ​SEEK_SET​

    ​:從檔案開頭移動offset個位元組
  • ​SEEK_CUR​

    ​:從目前位置移動offset個位元組
  • ​SEEK_END​

    ​:從檔案末尾移動offset個位元組
long ftell(FILE *stream);
      
  • 功能:擷取檔案流(檔案光标)的讀寫位置。
  • ​stream​

  • 成功:目前檔案流(檔案光标)的讀寫位置
void rewind(FILE *stream);
      
  • 功能:把檔案流(檔案光标)的讀寫位置移動到檔案開頭。
  • ​stream​

  • 無傳回值

随機位置讀取不同老師:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct _TEACHER {
char name[64];
int age;
}Teacher;

void test() {
//寫檔案
FILE* fp_write = NULL;
//寫方式打開檔案
fp_write = fopen("./mydata.txt", "wb");
if (fp_write == NULL) {
perror("fopen:");
return;
  }

Teacher teachers[4] = {
    { "1倩", 33 },
    { "2利", 28 },
    { "3Jos", 45},
    { "4咪咪", 35}
  };

for (int i = 0; i < 4; i++) {
fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
  }
//關閉檔案
fclose(fp_write);

//讀檔案
FILE* fp_read = NULL;
fp_read = fopen("./mydata.txt", "rb");
if (fp_read == NULL) {
perror("fopen:");
return;
  }

Teacher temp;
// 從檔案開頭移動:讀取第三個
fseek(fp_read, sizeof(Teacher) * 2, SEEK_SET);
fread(&temp, sizeof(Teacher), 1, fp_read);
printf("Name:%s Age:%d\n", temp.name, temp.age);

memset(&temp, 0, sizeof(Teacher));

// 從檔案末尾移動:讀取第四個
fseek(fp_read, -(int)sizeof(Teacher), SEEK_END);
fread(&temp, sizeof(Teacher), 1, fp_read);
printf("Name:%s Age:%d\n", temp.name, temp.age);

// 重新從檔案開頭讀取
rewind(fp_read);
fread(&temp, sizeof(Teacher), 1, fp_read);
printf("Name:%s Age:%d\n", temp.name, temp.age);

fclose(fp_read);
}

int main()
{
test();
return 0;
}
      
C語言 檔案操作相關函數

檔案操作綜合案例

繼續閱讀