C語言檔案操作完整指南|從基礎到進階,適合初學者的解說

目次

1. 前言

C語言是學習程式設計基礎時非常重要的語言,且在許多場合中被廣泛使用。其中「檔案建立」是程式處理外部資料時不可或缺的基本技術之一。本文將聚焦於 C 語言的檔案操作,特別是檔案建立,並以易於初學者理解的方式說明。

檔案操作的重要性

在執行程式後需要保存取得的資料,或是利用外部輸入資料時,都需要檔案操作。例如,在以下情境中檔案操作相當有用。
  • 日誌資料的保存 程式的運作紀錄與錯誤資訊會被記錄,之後可供分析。
  • 設定檔的管理 將使用者可變更的設定儲存於外部檔案,程式啟動時讀取。
  • 類似資料庫的使用 以檔案方式進行小規模資料的保存與管理。
這些應用範例在實際程式開發中常被需求。學習 C 語言的檔案建立,將大幅提升程式的實用性。

本文的目的

本文的目的在於讓首次學習使用 C 語言「建立檔案方法」的讀者,能夠理解基本的檔案操作,並自行撰寫程式碼執行。此外,亦會涉及錯誤處理與應用範例,旨在培養接近實務的技能。

目標讀者

本文的對象讀者如下:
  • 剛開始學習 C 語言的初學者
  • 想了解檔案操作基礎的人
  • 預計在程式中需要資料保存與讀寫的人

2. 檔案操作的基本概念

C語言中要操作檔案,首先需要了解檔案的基本概念。本節將說明「檔案是什麼」「文字檔與二進位檔的差異」「在 C 語言中執行檔案操作所需的準備」等內容。

檔案是什麼

檔案是一種用來記錄資料的容器。執行程式時,用於將資料儲存至外部,或從外部讀取程式所需的資訊。檔案主要分為以下兩類。
  1. 文字檔
  • 以人類易於閱讀的格式記錄資料的檔案。
  • 例如:.txt.csv 等。
  • 文字檔可以以行為單位儲存文字、數字、符號等。
  1. 二進位檔
  • 以電腦易於處理的格式記錄資料的檔案。
  • 例如:.bin.dat、影像檔(例如:.jpg.png)等。
  • 二進位檔不僅儲存文字,還可保存數值、影像資料等各種形式的資訊。

文字檔與二進位檔的差異

特徵文字檔二進位檔
資料格式人類可讀的格式(如 ASCII、UTF-8 等)電腦專用的格式
用途設定檔、日誌資料等影像、音訊、資料庫等
大小通常較大可更緊湊地儲存
操作的容易度可用編輯器輕鬆開啟只能以特定程式讀寫
重點: 初學者在學習 C 語言時,建議先掌握文字檔的操作,之後再進一步學習二進位檔的操作。

在 C 語言中進行檔案操作所需的準備

在 C 語言中,使用標準函式庫來操作檔案。需要以下準備。

標準標頭檔 <stdio.h>

<stdio.h> 是在 C 語言中執行檔案操作所需的標頭檔。此標頭檔包含用於檔案操作的函式。主要函式如下。
  • fopen: 開啟檔案。
  • fclose: 關閉檔案。
  • fprintf: 寫入檔案。
  • fscanf: 從檔案讀取。
  • fread / fwrite: 操作二進位資料。

檔案指標

在 C 語言中,執行檔案操作時會使用稱為「檔案指標」的特殊變數。檔案指標以 FILE 型別定義。
FILE *fp;
使用此檔案指標可開啟檔案,或讀寫資料。

檔案模式

操作檔案時必須指定模式。模式決定檔案的使用方式(唯讀、唯寫等)。以下整理主要模式。
模式用途
"r"唯讀(檔案必須已存在)
"w"唯寫(覆寫已存在的資料)
"a"追加寫入(保留已存在資料並在其後寫入)
"r+"讀寫(讀取與寫入)
"w+"讀寫(覆寫已存在資料)
"a+"讀取與追加寫入

總結

本節說明了檔案的基本概念與類型,以及在 C 語言中操作檔案所需的準備。
侍エンジニア塾

3. 檔案的開啟與關閉

C 語言中操作檔案的第一步是「開啟檔案」。正確開啟檔案後,就能進行資料的讀寫與編輯。另外,使用過的檔案必須一定要關閉。本節將以具體範例說明檔案的開啟與關閉方法。

開啟檔案:fopen 函式

在 C 語言中,使用 fopen 函式來開啟檔案。此函式的寫法如下。
FILE *fopen(const char *filename, const char *mode);

參數說明

  • filename:以字串指定檔名。例如:"example.txt"
  • mode:指定檔案的使用模式。例如:"r"(唯讀)、"w"(唯寫)等。

返回值

  • 若成功開啟檔案,會回傳 FILE 型別的指標。
  • 若無法開啟檔案,會回傳 NULL。此時需要進行錯誤處理。

基本使用範例:開啟檔案

以下範例示範以唯讀模式開啟 example.txt 檔案的程式。
#include <stdio.h>

int main() {
    FILE *file;

    // 開啟檔案
    file = fopen("example.txt", "r");

    // 檢查檔案是否成功開啟
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    printf("檔案已成功開啟。\n");

    // 關閉檔案
    fclose(file);

    return 0;
}
重點:
  • 若檔案未能正確開啟,會顯示錯誤訊息並結束程式。
  • 檔案操作結束後,務必使用 fclose 函式關閉檔案。

檔案模式的種類

依據開啟檔案時的模式,操作內容會有所不同。以下整理常用的模式列表。
模式用途
"r"唯讀(檔案必須已存在)
"w"唯寫(若檔案已存在,內容會被刪除)
"a"追加寫入(若檔案已存在,資料會被加在檔案末端)
"r+"讀寫(保留既有檔案內容)
"w+"讀寫(刪除既有檔案內容)
"a+"讀寫與追加(在檔案末端新增資料的同時,也能讀取內容)

關閉檔案:fclose 函式

檔案開啟後,使用完畢必須呼叫 fclose 函式關閉檔案。若忽略此步驟,可能會產生以下問題。
  • 記憶體洩漏(檔案指標未被釋放)
  • 資料寫入未完成
  • 系統資源浪費

基本語法

int fclose(FILE *stream);

返回值

  • 若檔案正常關閉,會回傳 0
  • 若發生錯誤,會回傳 EOF

範例:關閉檔案

以下示範關閉檔案的程式。
#include <stdio.h>

int main() {
    FILE *file;

    // 開啟檔案
    file = fopen("example.txt", "r");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    // 檔案操作(省略)

    // 關閉檔案
    if (fclose(file) == 0) {
        printf("檔案已成功關閉。\n");
    } else {
        printf("關閉檔案時發生錯誤。\n");
    }

    return 0;
}
重點:
  • 透過檢查 fclose 函式的返回值,可判斷檔案是否正常關閉。

錯誤檢查的重要性

在開啟或關閉檔案時,可能會發生錯誤。若在以下情況加入錯誤處理,可提升程式的可靠性。

主要錯誤原因

  • 指定的檔案不存在("r" 模式)
  • 沒有寫入權限
  • 檔名錯誤

錯誤處理範例

if (file == NULL) {
    perror("檔案開啟錯誤");
    return 1;
}
perror 函式可將錯誤原因顯示於標準輸出。

總結

  • fopen 函式用於開啟檔案,fclose 函式用於關閉檔案。
  • 正確指定檔案模式,並依操作需求選擇適當模式。
  • 加入錯誤處理,可提升檔案操作的安全性與可靠性。

4. 寫入檔案

在 C 語言中進行檔案操作時,寫入資料的方法非常重要。本節將說明如何使用 fprintffputsfputc 等函式將資料寫入檔案。此外,透過具體的範例程式碼學習實際的使用方式。

檔案寫入的基本

要將資料寫入檔案,需要遵循以下步驟。
  1. 開啟檔案(使用 fopen 函式) 若要寫入,模式需指定為 "w"(寫入專用)或 "a"(追加專用)。
  2. 使用寫入函式將資料保存至檔案。
  3. 寫入完成後,使用 fclose 函式關閉檔案。

寫入函式的種類

在 C 語言中,根據用途使用以下寫入函式。

1. fprintf 函式

fprintf 函式用於將格式化的資料寫入檔案。 語法
int fprintf(FILE *stream, const char *format, ...);
  • stream:寫入目標的檔案指標。
  • format:格式指定字串(例如 %d%s 等)。
  • 返回值:回傳成功寫入的字元數。
範例:寫入格式化資料
#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        printf("檔案無法開啟。
");
        return 1;
    }

    fprintf(file, "姓名: %sn年齡: %dn", "山田太郎", 25);
    fclose(file);

    printf("資料已成功寫入。
");
    return 0;
}

2. fputs 函式

fputs 函式用於將字串直接寫入檔案。 語法
int fputs(const char *str, FILE *stream);
  • str:要寫入的字串。
  • stream:寫入目標的檔案指標。
  • 返回值:成功時返回非 0,失敗時返回 EOF。
範例:寫入字串
#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        printf("檔案無法開啟。
");
        return 1;
    }

    fputs("你好,世界!n", file);
    fclose(file);

    printf("字串已成功寫入。
");
    return 0;
}

3. fputc 函式

fputc 函式用於逐字元寫入檔案。 語法
int fputc(int char, FILE *stream);
  • char:要寫入的字元(以 ASCII 值指定)。
  • stream:寫入目標的檔案指標。
  • 返回值:成功時返回寫入的字元,失敗時返回 EOF。
範例:逐字元寫入
#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        printf("檔案無法開啟。
");
        return 1;
    }

    fputc('H', file);
    fputc('e', file);
    fputc('l', file);
    fputc('l', file);
    fputc('o', file);
    fclose(file);

    printf("字元已成功寫入。
");
    return 0;
}

檔案模式與寫入

依據檔案模式,資料寫入的行為會不同。
  1. "w" 模式
  • 若檔案不存在,會新建檔案。
  • 若檔案已存在,會覆寫現有資料。
  1. "a" 模式
  • 若檔案不存在,會新建檔案。
  • 若檔案已存在,會保留現有資料,並在末尾追加新資料。

注意事項:寫入錯誤的處理

在檔案寫入時,可能會發生錯誤。例如,磁碟空間不足或缺乏寫入權限都可能是原因。加入錯誤處理可對這些問題加以因應。 錯誤處理範例
if (fprintf(file, "測試資料n") < 0) {
    printf("寫入過程中發生錯誤。
");
}

實作範例:簡易日誌檔案建立程式

以下為將日誌資料保存至檔案的程式範例。
#include <stdio.h>
#include <time.h>

int main() {
    FILE *file = fopen("log.txt", "a");
    if (file == NULL) {
        printf("日誌檔案無法開啟。
");
        return 1;
    }

    time_t now = time(NULL);
    fprintf(file, "日誌記錄: %s", ctime(&now));

    fclose(file);
    printf("日誌已成功記錄。
");
    return 0;
}

總結

  • 檔案寫入可使用 fprintffputsfputc 等函式。
  • 適當指定檔案模式("w""a"),以實現符合需求的行為。
  • 加入錯誤處理,可提升檔案操作的安全性。

5. 從檔案讀取

C 語言在進行檔案操作時,從檔案讀取資料也是基本技能之一。本節將說明使用 fscanffgetsfgetc 等函式的資料讀取方法。另外,透過具體範例學習實際從檔案取得資料的方法。

檔案讀取的基本

為了從檔案讀取資料,需要執行以下步驟。
  1. 開啟檔案(使用 fopen 函式) 讀取時,模式指定為 "r"(唯讀)。
  2. 使用讀取函式取得資料。
  3. 讀取結束後,使用 fclose 函式關閉檔案。

讀取函式的種類

在 C 語言中依需求使用以下函式讀取資料。

1. fscanf 函式

fscanf 函式用於從檔案讀取格式化資料。 語法
int fscanf(FILE *stream, const char *format, ...);
  • stream:要讀取的檔案指標。
  • format:讀取格式(例如 %d%s)。
  • 返回值:回傳成功讀取的項目數。失敗時回傳 EOF
範例:讀取格式化資料
#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    char name[50];
    int age;

    fscanf(file, "%s %d", name, &age);
    printf("姓名: %s, 年齡 %dn", name, age);

    fclose(file);
    return 0;
}

2. fgets 函式

fgets 函式適合逐行從檔案讀取資料。 語法
char *fgets(char *str, int n, FILE *stream);
  • str:存放讀取資料的陣列。
  • n:最大讀取字元數(不超過 str 的大小)。
  • stream:要讀取的檔案指標。
  • 返回值成功時回傳 str,失敗或 EOF 時回傳 NULL
範例:逐行讀取資料
#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    char line[100];

    while (fgets(line, sizeof(line), file) != NULL) {
        printf("%s", line);
    }

    fclose(file);
    return 0;
}

3. fgetc 函式

fgetc 函式用於逐字元從檔案讀取資料。 語法
int fgetc(FILE *stream);
  • stream:要讀取的檔案指標。
  • 返回值:回傳讀取的字元(ASCII 值)。失敗或 EOF 時回傳 <>EOF。
範例:逐字元讀取資料
#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    int c;
    while ((c = fgetc(file)) != EOF) {
        putchar(c);
    }

    fclose(file);
    return 0;
}

EOF(End Of File)的處理

EOF 是表示檔案結尾的特殊值。當讀取函式回傳 EOF 時,表示已到達檔案結尾。 確認 EOF 的範例
int c;
while ((c = fgetc(file)) != EOF) {
    putchar(c);
}
注意事項:
  • EOF 通常定義為 -1,但在程式中建議直接與 EOF 比較。

實作範例:讀取設定檔

以下為從設定檔(例如 config.txt)讀取設定資料的程式範例。 config.txt 的內容
username admin
password 12345
程式範例
#include <stdio.h>

int main() {
    FILE *file = fopen("config.txt", "r");
    if (file == NULL) {
        printf("無法開啟設定檔。\n");
        return 1;
    }

    char key[50], value[50];
    while (fscanf(file, "%s %s", key, value) != EOF) {
        printf("%s: %sn", key, value);
    }

    fclose(file);
    return 0;
}
執行結果
username: admin
password: 12345

總結

  • 從檔案讀取資料時,依需求使用 fscanffgetsfgetc 等函式。
  • 讀取檔案時,確認 EOF 以正確處理資料是很重要的。
  • 在實務上,可應用於讀取設定檔或日誌檔等。

6. 二進位檔案的操作

C語言中,也可以以二進位形式處理檔案。二進位檔案與文字檔不同,對人類而言較難閱讀,但資料大小較小,且可高速讀寫。本節將介紹操作二進位檔案的基礎知識與具體使用範例。

什麼是二進位檔案?

二進位檔案是以原始格式儲存資料的檔案。以下是二進位檔案的特點。
  1. 高效的資料儲存 在二進位格式中,資料會直接保存,因此比文字格式更有效率地儲存資料。
  2. 高度的通用性 用於影像檔、音訊檔、壓縮檔等各種格式。
  3. 對人類不可讀的格式 若直接用文字編輯器開啟已保存的資料,通常會看到亂碼。

操作二進位檔案的主要函式

在 C 語言中,使用 fread 函式與 fwrite 函式來讀寫二進位資料。

1. fread 函式

fread 函式在從檔案讀取二進位資料時使用。語法
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
  • ptr:存放讀取資料的指標。
  • size:單一資料的大小(以位元組為單位)。
  • count:要讀取的資料數量。
  • stream:要讀取的檔案指標。

2. fwrite 函式

fwrite 函式在將二進位資料寫入檔案時使用。語法
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
  • ptr:指向要寫入資料的指標。
  • size:單一資料的大小(以位元組為單位)。
  • count:要寫入的資料數量。
  • stream:寫入目標的檔案指標。

以二進位模式開啟檔案

操作二進位檔案時,需在 fopen 函式的模式中加入 "b"
  • "rb":二進位唯讀。
  • "wb":二進位唯寫。
  • "ab":二進位追加寫入。

範例:以二進位格式儲存數值資料

寫入資料的程式

以下為將整數資料以二進位格式儲存至檔案的程式。
#include <stdio.h>

int main() {
    FILE *file = fopen("data.bin", "wb");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    int numbers[] = {1, 2, 3, 4, 5};
    size_t size = sizeof(numbers) / sizeof(numbers[0]);

    fwrite(numbers, sizeof(int), size, file);

    fclose(file);
    printf("資料已以二進位格式儲存。\n");
    return 0;
}

讀取資料的程式

以下為讀取上述儲存的二進位資料的程式。
#include <stdio.h>

int main() {
    FILE *file = fopen("data.bin", "rb");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    int numbers[5];
    fread(numbers, sizeof(int), 5, file);

    printf("讀取的資料: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }

    fclose(file);
    return 0;
}
執行結果
讀取的資料: 1 2 3 4 5

二進位檔案操作的注意事項

  1. 資料大小的一致性 使用 freadfwrite 時,指定正確的大小非常重要。若指定錯誤的大小,會導致資料讀寫失敗。
  2. 錯誤檢查 若在檔案操作過程中發生錯誤,可使用 ferror 函式檢查錯誤狀態。
  3. 資料的可移植性 以二進位格式保存的檔案在不同平台間可能不相容。特別需要注意位元組序(大端序與小端序)的差異。

實作範例:結構體資料的儲存與讀取

儲存結構體的程式

以下為以二進位格式儲存結構體資料的範例。
#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

int main() {
    FILE *file = fopen("employee.bin", "wb");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    Employee emp = {"山田太郎", 30, 450000.0};
    fwrite(&emp, sizeof(Employee), 1, file);

    fclose(file);
    printf("已儲存員工資料。\n");
    return 0;
}

讀取結構體的程式

以下為讀取已儲存的結構體資料的程式。
#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;

int main() {
    FILE *file = fopen("employee.bin", "rb");
    if (file == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    Employee emp;
    fread(&emp, sizeof(Employee), 1, file);

    printf("姓名: %sn年齡: %dn薪資: %.2fn", emp.name, emp.age, emp.salary);

    fclose(file);
    return 0;
}
執行結果
姓名: 山田太郎
年齡: 30
薪資: 450000.00

總結

  • 二進位檔案能有效率地儲存資料,並使用 freadfwrite 進行操作。
  • 在檔案模式中指定code>”b” 以二進位模式開啟檔案。
  • 注意資料大小與錯誤檢查,確保正確的檔案操作。

7. 錯誤處理

檔案操作時,錯誤是無法避免的。C 語言中,當錯誤發生時適當處理,可提升程式的可靠性與穩定性。本節將說明檔案操作中常見的錯誤,以及偵測與解決的方法。

檔案操作中常見的主要錯誤

以下列出在 C 語言中執行檔案操作時可能發生的一般錯誤。
  1. 無法開啟檔案
  • 原因:檔案不存在、路徑錯誤,或是權限不足。
  • 解決方法:檢查 fopen 的返回值以處理錯誤。
  1. 寫入或讀取錯誤
  • 原因:磁碟空間不足,或檔案被設為唯讀。
  • 解決方法:在寫入或讀取操作後檢查錯誤。
  1. 檔案已達結尾(EOF)
  • 原因:已讀取至檔案末端。
  • 解決方法:正確處理 EOF。
  1. 檔案指標的錯誤使用
  • 原因:檔案指標無效或已被關閉。
  • 解決方法:確認指標是否為 NULL。

錯誤偵測的基本方法

1. 確認 fopen 函式的返回值

fopen 函式在成功開啟檔案時會返回檔案指標,若發生錯誤則返回 NULL範例:無法開啟檔案時的處理
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
    perror("檔案開啟錯誤");
    return 1;
}
要點:
  • perror 函式會輸出剛發生的錯誤的詳細說明。

2. 確認寫入與讀取錯誤

使用 fwritefread 後,確認資料是否正確處理。 範例:fwrite 後的錯誤確認
size_t written = fwrite(data, sizeof(int), 5, file);
if (written < 5) {
    printf("資料寫入錯誤發生。\n");
}
範例:fread 後的錯誤確認
size_t read = fread(data, sizeof(int), 5, file);
if (read < 5) {
    if (feof(file)) {
        printf("已到達檔案結尾。\n");
    } else if (ferror(file)) {
        printf("讀取時發生錯誤。\n");
    }
}

3. 使用 feof 函式與 ferror 函式

  • feof 函式 確認檔案是否已達結尾。 返回值:若已達結尾則返回非零值。
  • ferror 函式 確認檔案操作過程中是否發生錯誤。 返回值:若發生錯誤則返回非零值。
範例:在檔案讀取過程中確認 EOF 與錯誤
int c;
while ((c = fgetc(file)) != EOF) {
    putchar(c);
}

if (feof(file)) {
    printf("已到達檔案結尾。\n");
} else if (ferror(file)) {
    printf("檔案讀取時發生錯誤。\n");
}

錯誤處理的最佳實踐

  1. 盡早進行錯誤處理 在開啟檔案階段偵測錯誤,避免影響後續程式執行。
  2. 顯示詳細的錯誤訊息 讓使用者或開發者更容易定位問題,清楚傳達錯誤內容。
  3. 確保資源正確釋放 即使發生錯誤,也要適當關閉已開啟的檔案。
範例:檔案操作中的資源釋放
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
    perror("檔案開啟錯誤");
    return 1;
}

// 檔案操作(省略)

if (fclose(file) != 0) {
    printf("檔案關閉錯誤發生。\n");
}

實作範例:安全的檔案讀取程式

以下為在檔案讀取過程中安全處理錯誤的程式範例。
#include 

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("檔案開啟錯誤");
        return 1;
    }

    char buffer[100];
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }

    if (feof(file)) {
        printf("\n正常讀取檔案。\n");
    } else if (ferror(file)) {
        printf("\n讀取時發生錯誤。\n");
    }

    fclose(file);
    return 0;
}

總結

  • 在檔案操作過程中的錯誤,可透過檢查 fopenfwritefread 等函式的返回值來偵測。
  • 使用 feofferror 來詳細確認檔案狀態。
  • 適當實作錯誤處理,可提升程式的可靠性與穩定性。

8. 應用

C語言的檔案操作了解後,挑戰進階的操作吧。本節將介紹多檔案同時操作、暫存檔的使用、檔案重新命名與刪除等進階技巧。透過學習這些,您將能夠製作更實務的程式。

多檔案同時操作

C語言中,可以同時開啟多個檔案並操作。藉此可以將日誌檔與錯誤檔分別記錄,實現更複雜的操作。

範例:同時操作日誌檔與錯誤檔

#include <stdio.h>

int main() {
    FILE *logFile = fopen("log.txt", "w");
    FILE *errorFile = fopen("error.txt", "w");

    if (logFile == NULL || errorFile == NULL) {
        printf("無法開啟檔案。\n");
        return 1;
    }

    fprintf(logFile, "日誌: 程式正常執行。\n");
    fprintf(errorFile, "錯誤: 偵測到未預期的輸入。\n");

    fclose(logFile);
    fclose(errorFile);

    printf("已記錄日誌與錯誤。\n");
    return 0;
}
重點:
  • 利用多個FILE指標,將不同目的的資料分別儲存於不同檔案。
  • 確保所有開啟的檔案都能正確關閉。

暫存檔的使用

暫存檔用於程式執行期間暫時保存資料。程式結束時會自動刪除,從安全性與資源管理的角度來說相當便利。

使用 tmpfile 函式建立暫存檔

tmpfile函式可輕鬆建立暫存檔。 範例:暫存檔的使用
#include <stdio.h>

int main() {
    FILE *tempFile = tmpfile();
    if (tempFile == NULL) {
        printf("無法建立暫存檔。\n");
        return 1;
    }

    fprintf(tempFile, "此資料暫時保存。\n");

    // 讀取暫存檔內容
    rewind(tempFile);
    char buffer[100];
    fgets(buffer, sizeof(buffer), tempFile);
    printf("暫存檔內容: %s", buffer);

    // 暫存檔會自動刪除
    fclose(tempFile);

    return 0;
}
重點:
  • 若要重新利用暫存檔內容,請使用rewind函式將檔案指標移回開頭。
  • 檔案會在程式結束時自動刪除,無需手動刪除。

檔案的重新命名與刪除

在 C 語言中,可以對既有檔案進行重新命名(改名)或刪除。

rename 函式:檔名變更

語法
int rename(const char *oldname, const char *newname);
  • oldname:變更前的檔名。
  • newname:變更後的檔名。
  • 返回值:成功時返回 0,失敗時返回非零值。
範例:檔名變更
#include <stdio.h>

int main() {
    if (rename("oldfile.txt", "newfile.txt") == 0) {
        printf("已變更檔名。\n");
    } else {
        printf("檔名變更失敗。\n");
    }

    return 0;
}

remove 函式:檔案刪除

語法
int remove(const char *filename);
  • filename:要刪除的檔名。
  • 返回值:成功時返回 0,失敗時返回非零值。
範例:檔案刪除
#include <stdio.h>

int main() {
    if (remove("unnecessary.txt") == 0) {
        printf("已刪除檔案。\n");
    } else {
        printf("檔案刪除失敗。\n");
    }

    return 0;
}
重點:
  • 建議在變更或刪除檔名之前,先確認檔案是否存在。
  • 若刪除或重新命名失敗,請檢查錯誤原因。

實作範例:檔案管理工具

以下是結合重新命名與刪除的簡易檔案管理程式範例。
#include <stdio.h>

int main() {
    // 變更檔名
    if (rename("tempfile.txt", "finalfile.txt") == 0) {
        printf("已將檔名變更為 'finalfile.txt'。\n");
    } else {
        printf("檔名變更失敗。\n");
    }

    // 刪除檔案
    if (remove("finalfile.txt") == 0) {
        printf("已刪除檔案 'finalfile.txt'。\n");
    } else {
        printf("檔案刪除失敗。\n");
    }

    return 0;
}

總結

  • 同時操作多個檔案,可構建更複雜的程式。
  • 使用暫存檔可提升安全性與效率。
  • 使用 renameremove,即可輕鬆管理檔案。

9. FAQ(常見問題)

在此,我們將以問答形式說明關於 C 語言檔案操作,讀者常有的疑問點。從基本疑問到進階內容,提供您加深理解的參考。

Q1: fopen函式無法開啟檔案的原因是什麼?

A1: 可能的原因如下:
  1. 檔案不存在(在 "r" 模式下)。
  2. 檔案路徑錯誤。
  3. 沒有讀取或寫入的權限。
  4. 磁碟空間不足。
解決方法:
  • 請確認檔案名稱與路徑。
  • 若檔案不存在,請使用 "w" 模式或 "a" 模式新建。
  • 檢查檔案權限,並賦予適當的權限。

Q2: "w" 模式與 "a" 模式的差異是什麼?

A2:
  • "w" 模式(僅寫入)
  • 若檔案已存在,其內容將全部被刪除。
  • 若檔案不存在,將會新建。
  • "a" 模式(僅追加)
  • 若檔案已存在,保留原有內容,新的資料會被追加至尾端。
  • 若檔案不存在,將會新建。

Q3: 文字檔與二進位檔的差異是什麼?

A3:
特徵文字檔二進位檔
資料格式人類可讀的格式(如 ASCII、UTF-8 等)電腦專用的格式
用途設定檔、日誌資料等影像、音訊、資料庫等
大小通常較大可更緊湊儲存
操作的便利性可用編輯器輕鬆開啟只能透過特定程式讀寫
重點: 初學者建議先從文字檔操作開始。

Q4: 若在檔案操作過程中發生錯誤,該如何處理?

A4: 發生錯誤時,請確認以下項目:
  1. 檔案指標的確認: 開檔時確認 fopen 是否未返回 NULL。
  2. 錯誤訊息的顯示: 使用 perror 函式顯示詳細錯誤資訊。
  3. 活用 ferrorfeof 在讀寫過程中若發生錯誤,使用這些函式檢查狀態。

Q5: 若不關閉檔案會發生什麼情況?

A5:
  • 資料可能無法正確保存。
  • 已開啟的檔案若未關閉,會導致記憶體洩漏或資源不足。
  • 特別是程式同時開啟多個檔案時,未關閉的檔案增多會增加系統負荷。
解決方法:
  • 務必使用 fclose 函式,並加入錯誤處理。

Q6: 在讀寫二進位檔時需注意哪些事項?

A6:
  • 資料大小: 使用 freadfwrite 時,正確設定資料大小。
  • 位元組順序的差異: 在不同平台間使用二進位檔時,請注意位元組順序(大端序與小端序)的差異。
  • 資料完整性: 正確開關檔案,避免資料遺失。

Q7: EOF(檔案結尾)是什麼?

A7: EOF(End Of File)是表示已到達檔案結尾的特殊值。可使用以下函式檢查 EOF:
  • fgetc
  • fgets
  • fscanf
檢查 EOF 的範例:
int c;
while ((c = fgetc(file)) != EOF) {
    putchar(c);
}
注意: EOF 通常定義為 -1,但在程式中建議使用 EOF 進行比較。

Q8: 如何有效學習 C 語言的檔案操作?

A8:
  • 紮實學習基礎: 掌握 fopenfclosefprintffscanf 等基本函式的使用方法。
  • 實作專案: 透過保存日誌檔或建立簡易資料庫等小型專案,深化理解。

總結

  • 在 FAQ 章節中,我們全面說明了關於 C 語言檔案操作的常見問題。
  • 請學習從基本操作到錯誤處理的實用知識。
  • 若有不明之處,請先參考文件或參考手冊。

10. 總結

在本文中,我們系統性地解說了 C 語言的檔案操作,從基礎到應用。檔案操作是程式與外部資料交互不可或缺的技術,且可廣泛應用於各種用途。本節將回顧全文要點,並介紹面向下一步的建議。

重點回顧

1. 基本概念

  • 檔案分為文字格式與二進位格式,各自用途不同。
  • 在 C 語言進行檔案操作時,使用 <stdio.h> 標頭檔。

2. 檔案操作的基本

  • 使用 fopen 函式開啟檔案,選擇適當的模式(例如:"r", "w")。
  • 開啟檔案後,必須使用 fclose 函式關閉。

3. 寫入與讀取

  • 寫入時,使用 fprintffputs 等將資料保存。
  • 讀取時,使用 fscanffgets 從檔案取得資料。

4. 二進位檔案操作

  • 在二進位檔案中,使用 freadfwrite 高效地讀寫資料。
  • 透過保存與讀取結構體,可處理複雜的資料結構。

5. 錯誤處理

  • 考慮檔案操作中可能發生錯誤,加入使用 ferrorfeof 的錯誤處理。

6. 應用操作

  • 熟練同時操作多個檔案、使用暫存檔、檔案重新命名與刪除等應用技巧,即可構建更實務的程式。

對下一步的建議

掌握 C 語言檔案操作的基礎後,挑戰以下步驟吧。
  1. CSV 與 JSON 檔案的操作
  • 根據檔案格式建立對應的解析器,實作資料的讀寫。
  • 例:將學生成績資料保存為 CSV 檔案,讀取後進行分析。
  1. 加強錯誤處理
  • 建立記錄檔案操作錯誤的日誌系統,提高程式的可靠性。
  1. 多執行緒環境下的檔案操作
  • 學習在多執行緒中安全操作檔案的方法。
  1. 利用檔案操作的專案開發
  • 開發實務程式,深化檔案操作技能。
  • 例:簡易資料庫、設定管理工具、日誌收集程式等。

最後

C 語言的檔案操作是提升程式實用性的重要技能。雖然起初可能感到困難,但只要掌握基礎並不斷實踐,就能確實深化理解。希望透過本文,您能對檔案操作充滿信心,並建立挑戰更複雜專案的基礎。