Clanguagefileoperationtutorial

LearningClanguagefile 打开 and 关闭, 文本file and 二进制file 读写operation, file位置指针 operation

返回tutoriallist

1. fileoperationoverview

1.1 what is file

file is store in out 部store设备 (such as硬盘, U盘etc.) on 一组相关data collection. in Clanguagein, file可以分 for 两种class型:

  • 文本file: 以字符形式storedata, 每个字符 for 应一个ASCII码值, 适合store可阅读 文本data.
  • 二进制file: 以二进制形式storedata, 直接storedata 二进制表示, 适合storegraph像, 音频, 视频etc.非文本data, 以及需要 high 效store 数值data.

1.2 file指针

in Clanguagein, fileoperation is throughfile指针来for . file指针 is a 指向FILEclass型structure 指针, FILEstructure定义 in stdio.h头filein, package含了file 相关information, such asfile 位置指针, file 打开模式etc..

// 声明file指针
FILE *fp;

2. file 打开 and 关闭

2.1 file 打开

usingfopenfunction打开file, 该function 原型such as under :

FILE *fopen(const char *filename, const char *mode);

其in:

  • filename: 要打开 file path and 名称.
  • mode: file 打开模式, 指定了file operation方式.
  • return value: 成功打开file时, 返回指向该file file指针; 失败时, 返回NULL.

常用 file打开模式:

"r"   - 只读模式, 打开一个已存 in  文本file
"w"   - 只写模式, creation一个 new  文本file, such as果file已存 in 则清空其 in 容
"a"   - 追加模式, 打开一个文本file,  in file末尾添加data, such as果file不存 in 则creation
"rb"  - 只读模式, 打开一个已存 in  二进制file
"wb"  - 只写模式, creation一个 new  二进制file, such as果file已存 in 则清空其 in 容
"ab"  - 追加模式, 打开一个二进制file,  in file末尾添加data, such as果file不存 in 则creation
"r+"  - 读写模式, 打开一个已存 in  文本file
"w+"  - 读写模式, creation一个 new  文本file, such as果file已存 in 则清空其 in 容
"a+"  - 读写模式, 打开一个文本file,  in file末尾添加data, such as果file不存 in 则creation
"rb+" - 读写模式, 打开一个已存 in  二进制file
"wb+" - 读写模式, creation一个 new  二进制file, such as果file已存 in 则清空其 in 容
"ab+" - 读写模式, 打开一个二进制file,  in file末尾添加data, such as果file不存 in 则creation

2.2 file 关闭

usingfclosefunction关闭file, 该function 原型such as under :

int fclose(FILE *stream);

其in:

  • stream: 要关闭 file指针.
  • return value: 成功关闭file时, 返回0; 失败时, 返回EOF (-1) .

关闭file important 性:

  • 释放file指针占用 resource
  • 确保所 has 缓冲区 data被写入file
  • 防止file被other程序占用

2.3 example: 打开 and 关闭file

#include <stdio.h>

int main() {
    FILE *fp;
    
    // 打开file
    fp = fopen("test.txt", "w");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    printf("file打开成功\n");
    
    // 关闭file
    if (fclose(fp) == 0) {
        printf("file关闭成功\n");
    } else {
        printf("file关闭失败\n");
    }
    
    return 0;
}

3. 文本file 读写operation

3.1 写入文本file

常用 写入文本file function:

3.1.1 fprintffunction

int fprintf(FILE *stream, const char *format, ...);

and printffunctionclass似, 但 is 将输出写入 to 指定 filein.

#include <stdio.h>

int main() {
    FILE *fp;
    int num = 100;
    float score = 95.5;
    char name[] = "张三";
    
    // 打开file
    fp = fopen("test.txt", "w");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 写入data
    fprintf(fp, "姓名: %s\n", name);
    fprintf(fp, "年龄: %d\n", num);
    fprintf(fp, "成绩: %.1f\n", score);
    
    // 关闭file
    fclose(fp);
    
    printf("data写入成功\n");
    
    return 0;
}

3.1.2 fputsfunction

int fputs(const char *s, FILE *stream);

将string写入 to 指定 filein.

#include <stdio.h>

int main() {
    FILE *fp;
    char str[] = "Hello, World!";
    
    // 打开file
    fp = fopen("test.txt", "w");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 写入string
    fputs(str, fp);
    fputs("\n", fp);  // 写入换行符
    fputs("Welcome to C programming!", fp);
    
    // 关闭file
    fclose(fp);
    
    printf("string写入成功\n");
    
    return 0;
}

3.1.3 putcfunction

int putc(int c, FILE *stream);

将单个字符写入 to 指定 filein.

#include <stdio.h>

int main() {
    FILE *fp;
    char ch;
    
    // 打开file
    fp = fopen("test.txt", "w");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 写入字符
    for (ch = 'A'; ch <= 'Z'; ch++) {
        putc(ch, fp);
    }
    putc('\n', fp);  // 写入换行符
    
    // 关闭file
    fclose(fp);
    
    printf("字符写入成功\n");
    
    return 0;
}

3.2 读取文本file

常用 读取文本file function:

3.2.1 fscanffunction

int fscanf(FILE *stream, const char *format, ...);

and scanffunctionclass似, 但 is from 指定 filein读取输入.

#include <stdio.h>

int main() {
    FILE *fp;
    char name[50];
    int age;
    float score;
    
    // 打开file
    fp = fopen("test.txt", "r");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 读取data
    fscanf(fp, "姓名: %s\n", name);
    fscanf(fp, "年龄: %d\n", &age);
    fscanf(fp, "成绩: %f\n", &score);
    
    // 输出读取 data
    printf("读取 data:\n");
    printf("姓名: %s\n", name);
    printf("年龄: %d\n", age);
    printf("成绩: %.1f\n", score);
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

3.2.2 fgetsfunction

char *fgets(char *s, int size, FILE *stream);

from 指定 filein读取一行字符, store to 字符arrayin.

#include <stdio.h>

int main() {
    FILE *fp;
    char buffer[100];
    
    // 打开file
    fp = fopen("test.txt", "r");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 读取file in 容
    printf("file in 容:\n");
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        printf("%s", buffer);
    }
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

3.2.3 getcfunction

int getc(FILE *stream);

from 指定 filein读取单个字符.

#include <stdio.h>

int main() {
    FILE *fp;
    int ch;
    
    // 打开file
    fp = fopen("test.txt", "r");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 读取file in 容
    printf("file in 容:\n");
    while ((ch = getc(fp)) != EOF) {
        putchar(ch);
    }
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

4. 二进制file 读写operation

4.1 写入二进制file

usingfwritefunction写入二进制file:

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);

其in:

  • ptr: 指向要写入data memory地址.
  • size: 每个data项 big small (以字节 for 单位) .
  • count: 要写入 data项 数量.
  • stream: file指针.
  • return value: 成功写入 data项 数量.
#include <stdio.h>

int main() {
    FILE *fp;
    int numbers[] = {10, 20, 30, 40, 50};
    int n = sizeof(numbers) / sizeof(numbers[0]);
    
    // 打开二进制file
    fp = fopen("data.bin", "wb");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 写入data
    size_t written = fwrite(numbers, sizeof(int), n, fp);
    printf("成功写入 %zu 个整数\n", written);
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

4.2 读取二进制file

usingfreadfunction读取二进制file:

size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

其in:

  • ptr: 指向store读取data memory地址.
  • size: 每个data项 big small (以字节 for 单位) .
  • count: 要读取 data项 最 big 数量.
  • stream: file指针.
  • return value: 成功读取 data项 数量.
#include <stdio.h>

int main() {
    FILE *fp;
    int numbers[5];
    int i;
    
    // 打开二进制file
    fp = fopen("data.bin", "rb");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 读取data
    size_t read = fread(numbers, sizeof(int), 5, fp);
    printf("成功读取 %zu 个整数\n", read);
    
    // 输出读取 data
    printf("读取 data: ");
    for (i = 0; i < read; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

5. file位置指针 operation

5.1 file位置指针

file位置指针 is a 指向filein当 before 读写位置 指针. 当打开一个file时, file位置指针 初始位置取决于file 打开模式:

  • for 于"r", "rb"模式, file位置指针指向file 开头.
  • for 于"w", "wb"模式, file位置指针指向file 开头, 并且file被清空.
  • for 于"a", "ab"模式, file位置指针指向file 末尾.

5.2 file位置指针 operationfunction

5.2.1 ftellfunction

long ftell(FILE *stream);

获取当 before file位置指针 位置 (相 for 于file开头 偏移量, 以字节 for 单位) .

5.2.2 fseekfunction

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

设置file位置指针 位置.

其in:

  • offset: 偏移量, 以字节 for 单位.
  • whence: 基准位置, 取值 for :
  • SEEK_SET: 以file开头 for 基准.
  • SEEK_CUR: 以当 before 位置 for 基准.
  • SEEK_END: 以file末尾 for 基准.

5.2.3 rewindfunction

void rewind(FILE *stream);

将file位置指针reset to file 开头, 相当于fseek(stream, 0, SEEK_SET).

#include <stdio.h>

int main() {
    FILE *fp;
    char buffer[100];
    long position;
    
    // 打开file
    fp = fopen("test.txt", "r");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        printf("file打开失败\n");
        return 1;
    }
    
    // 读取第一行
    fgets(buffer, sizeof(buffer), fp);
    printf("第一行: %s", buffer);
    
    // 获取当 before 位置
    position = ftell(fp);
    printf("当 before 位置: %ld 字节\n", position);
    
    // 读取第二行
    fgets(buffer, sizeof(buffer), fp);
    printf("第二行: %s", buffer);
    
    // reset to file开头
    rewind(fp);
    printf("reset to file开头\n");
    
    // 再次读取第一行
    fgets(buffer, sizeof(buffer), fp);
    printf("再次读取第一行: %s", buffer);
    
    // usingfseek设置位置
    fseek(fp, position, SEEK_SET);
    printf("设置 to 之 before  位置\n");
    
    // 再次读取第二行
    fgets(buffer, sizeof(buffer), fp);
    printf("再次读取第二行: %s", buffer);
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

6. fileoperation errorprocessing

6.1 error检测

in forfileoperation时, 应该始终checkfunction return value, 以检测可能发生 error:

  • for 于fopen, checkreturn value is 否 for NULL.
  • for 于fclose, checkreturn value is 否 for 0.
  • for 于fread, fwrite, checkreturn value is 否etc.于request 数量.
  • for 于fscanf, fgetsetc., checkreturn value is 否符合预期.

6.2 errorinformation

usingperrorfunction可以打印 and 当 before error码 for 应 errorinformation:

#include <stdio.h>

int main() {
    FILE *fp;
    
    // 尝试打开一个不存 in  file
    fp = fopen("nonexistent.txt", "r");
    
    // checkfile is 否成功打开
    if (fp == NULL) {
        perror("file打开失败");
        return 1;
    }
    
    // 关闭file
    fclose(fp);
    
    return 0;
}

7. file delete and rename

7.1 deletefile

usingremovefunctiondeletefile:

int remove(const char *filename);

成功deletefile时返回0, 失败时返回非零值.

7.2 renamefile

usingrenamefunctionrenamefile:

int rename(const char *oldname, const char *newname);

成功renamefile时返回0, 失败时返回非零值.

#include <stdio.h>

int main() {
    // renamefile
    if (rename("old.txt", "new.txt") == 0) {
        printf("filerename成功\n");
    } else {
        perror("filerename失败");
    }
    
    // deletefile
    if (remove("test.txt") == 0) {
        printf("filedelete成功\n");
    } else {
        perror("filedelete失败");
    }
    
    return 0;
}

实践case: 学生informationmanagementsystem (fileversion)

writing一个C程序, usingfilestore学生information, implementation添加学生information, 显示学生information, find学生information and 保存学生information to file functions.

requirementsanalysis

  • store many 个学生 information (姓名, 年龄, 成绩)
  • 添加学生information
  • 显示所 has 学生information
  • 根据姓名find学生information
  • 保存学生information to file
  • from file加载学生information

referencecode

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

// 声明学生structure体
typedef struct {
    char name[50];
    int age;
    float score;
} Student;

// function声明
void addStudent(Student students[], int *count);
void displayStudents(Student students[], int count);
void searchStudent(Student students[], int count);
void saveStudents(Student students[], int count, const char *filename);
void loadStudents(Student students[], int *count, const char *filename);

int main() {
    Student students[50];  // 最 many store50个学生
    int count = 0;         // 当 before 学生数量
    int choice;
    
    //  from file加载学生information
    loadStudents(students, &count, "students.dat");
    
    do {
        printf("\n学生informationmanagementsystem\n");
        printf("1. 添加学生information\n");
        printf("2. 显示所 has 学生information\n");
        printf("3. find学生information\n");
        printf("4. 保存学生information to file\n");
        printf("5. 退出\n");
        printf("请选择operation: ");
        scanf("%d", &choice);
        
        switch (choice) {
            case 1:
                addStudent(students, &count);
                break;
            case 2:
                displayStudents(students, count);
                break;
            case 3:
                searchStudent(students, count);
                break;
            case 4:
                saveStudents(students, count, "students.dat");
                break;
            case 5:
                // 退出 before 保存学生information
                saveStudents(students, count, "students.dat");
                printf("退出system\n");
                break;
            default:
                printf("无效选择, 请重 new 输入\n");
        }
    } while (choice != 5);
    
    return 0;
}

// 添加学生information
void addStudent(Student students[], int *count) {
    if (*count >= 50) {
        printf("学生数量已达 on 限\n");
        return;
    }
    
    printf("请输入学生information:\n");
    printf("姓名: ");
    scanf("%s", students[*count].name);
    printf("年龄: ");
    scanf("%d", &students[*count].age);
    printf("成绩: ");
    scanf("%f", &students[*count].score);
    
    (*count)++;
    printf("添加成功\n");
}

// 显示所 has 学生information
void displayStudents(Student students[], int count) {
    if (count == 0) {
        printf("暂无学生information\n");
        return;
    }
    
    printf("所 has 学生information:\n");
    printf("--------------------------------------------------\n");
    printf("姓名\t\t年龄\t成绩\n");
    printf("--------------------------------------------------\n");
    
    for (int i = 0; i < count; i++) {
        printf("%s\t\t%d\t%.1f\n", 
               students[i].name, students[i].age, students[i].score);
    }
    printf("--------------------------------------------------\n");
}

// 根据姓名find学生information
void searchStudent(Student students[], int count) {
    if (count == 0) {
        printf("暂无学生information\n");
        return;
    }
    
    char name[50];
    printf("请输入要find 学生姓名: ");
    scanf("%s", name);
    
    int found = 0;
    for (int i = 0; i < count; i++) {
        if (strcmp(students[i].name, name) == 0) {
            printf("找 to 学生information:\n");
            printf("姓名: %s\n", students[i].name);
            printf("年龄: %d\n", students[i].age);
            printf("成绩: %.1f\n", students[i].score);
            found = 1;
            break;
        }
    }
    
    if (!found) {
        printf("未找 to 该学生information\n");
    }
}

// 保存学生information to file
void saveStudents(Student students[], int count, const char *filename) {
    FILE *fp;
    
    // 打开file
    fp = fopen(filename, "wb");
    if (fp == NULL) {
        printf("file打开失败\n");
        return;
    }
    
    // 写入学生数量
    fwrite(&count, sizeof(int), 1, fp);
    
    // 写入学生information
    if (count > 0) {
        fwrite(students, sizeof(Student), count, fp);
    }
    
    // 关闭file
    fclose(fp);
    
    printf("学生information保存成功\n");
}

//  from file加载学生information
void loadStudents(Student students[], int *count, const char *filename) {
    FILE *fp;
    
    // 打开file
    fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("file打开失败, using空list\n");
        *count = 0;
        return;
    }
    
    // 读取学生数量
    fread(count, sizeof(int), 1, fp);
    
    // 读取学生information
    if (*count > 0) {
        fread(students, sizeof(Student), *count, fp);
    }
    
    // 关闭file
    fclose(fp);
    
    printf("学生information加载成功, 共 %d 个学生\n", *count);
}

互动练习

练习1: writing一个C程序, from 键盘输入一些文本, 将其写入 to 一个文本filein, 然 after 再 from 该filein读取 in 容并显示 in 屏幕 on .

提示: usingfgetsfunction from 键盘输入文本, usingfputsfunction写入file, 然 after usingfgetsfunction读取file in 容并显示.

练习2: writing一个C程序, statistics一个文本filein单词 数量.

提示: usingfscanffunction读取filein 单词, 直 to 遇 to EOF.

练习3: writing一个C程序, 将一个文本file in 容copy to 另一个文本filein.

提示: usinggetcfunction from sourcesfile读取字符, usingputcfunction将字符写入 to 目标filein.