C语言:文件操作

本文详细解释了在C语言中如何使用文件进行数据持久化,介绍了文件的概念、类型(程序文件和数据文件)、文件名结构、文件的打开与关闭、顺序和随机读写操作,以及如何使用feof和rewind进行文件指针管理。
摘要由CSDN通过智能技术生成

为什么使用文件

在之前的通讯录程序中,我们介绍了如何使用文件来实现数据的持久化。然而,我们只是创建了储存功能,但只限于程序运行时。在程序退出以后,数据就不存在了。为了解决这个问题,我们通常会将数据存储到磁盘文件或数据库中。
使用文件我们可以将数据存放到电脑硬盘上,做到数据持久化

什么是文件

文件是指在磁盘或其他存储媒体上存储数据的一种数据结构。在程序设计中有两种文件:程序文件和数据文件。

程序文件

包括源程序(后缀位.c),目标文件(后缀为.obj),可执行文件(后缀为.exe)。

数据文件

文件的内容不一定是程序,而是程序运行时读写的数据。

文件名

文件名包括了三个部分:文件路径+文件名主干+文件后缀
eg:c:\code\test.txt#

文件的打开和关闭

文件指针

缓冲文件系统中关键概念是文件类型指针,简称文件指针。
每次被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件名,文件状态和文件的当前位置),这些信息保存在一个结构体变量中,该结构体变量由系统声明,取名:FILE。
在不同的编译环境下,FILE包含的内容大同小异。
每打开一个文件,系统会根据文件情况自动创建一个FILE,并填充其中信息
对一个程序员来说,一般通过FILE的指针来维护FILE结构变量。
在这里插入图片描述

文件的打开和关闭

文件在读写前应先打开文件,结束后应关闭文件。
在编写程序时,打开文件时会返回一个FILE的指针指向改文件,建立了指针与文件的关系。
ANIC规定用
fopen打开文件fclose*关闭文件

fopen

FILE * fopen(const charfilename,const char mode)

filename:这是一个字符串,包含了您想要打开的文件的路径。这个路径可以是相对路径或绝对路径。

相对路径:相对路径(Relative Path)是相对于当前工作目录(或者当前文件的位置)的路径。它不包含从根目录(如 Unix 系统中的 /,Windows 系统中的 C:\)开始的全部信息,而是从当前目录开始到目标文件或目录的路径。

例如,如果您的当前工作目录是 /home/user/documents,那么相对路径 subfolder/file.txt 指的是 /home/user/documents/subfolder/file.txt。
绝对路径:绝对路径(Absolute Path)是一个完整的文件系统路径,它从文件系统的根目录开始,指定了文件或目录在文件系统中的确切位置。无论当前工作目录在哪里,绝对路径都能正确地定位到目标文件或目录。
mode:fopen 函数可以使用多种模式来打开文件。下面是所有有效的模式字符串列表:

“r”: 打开文件用于读取。如果文件不存在,fopen 返回 NULL。
“w”: 打开文件用于写入。如果文件存在,则清空内容;如果文件不存在,则创建新文件。
“a”: 打开文件用于追加。如果文件存在,数据将被追加到文件末尾;如果文件不存在,则创建新文件。
“r+”: 打开文件用于读写。如果文件不存在,fopen 返回 NULL。
“w+”: 打开文件用于读写。如果文件存在,则清空内容;如果文件不存在,则创建新文件。
“a+”: 打开文件用于读取和追加。如果文件存在,数据将被追加到文件末尾;如果文件不存在,则创建新文件。
“rb”: 打开二进制文件用于读取。
“wb”: 打开二进制文件用于写入。
“ab”: 打开二进制文件用于追加。
“rb+”: 打开二进制文件用于读写。
“wb+”: 打开二进制文件用于读写。
“ab+”: 打开二进制文件用于读取和追加。
此外,还可以在模式字符串中包含以下特殊字符:

“t”: 文本模式(默认值)。
“b”: 二进制模式。
“+”: 同时进行读写操作。

eg:
FILE* pf=fopen(“data.txt”,“r”);
尝试打开名为 data.txt 的文件,以便进行读取操作。如果文件存在且打开成功,fopen 函数将返回一个指向 FILE 对象的指针,该指针可以用来 subsequent I/O 操作。如果文件不存在或者由于其他原因无法打开,fopen 函数将返回 NULL。

fclose

int fclose(FILE *stream);
参数说明:

stream: 这是一个 FILE 类型的指针,它指向之前通过 fopen 函数打开的文件。
函数返回值:

如果关闭成功,fclose 函数返回 0。
如果发生错误,fclose 函数返回 EOF(-1 的宏定义)。
功能说明:

当您完成文件的读写操作后,应该使用 fclose 函数来关闭文件。这不仅会释放文件描述符和相关资源,还会确保所有的缓冲区内容都被刷新到文件中,从而确保数据的持久保存。

文件的顺序读写

函数名称作用原型返回值说明
fgetc从文件中读取一个字符int fgetc(FILE *stream);读取的字符或 EOF每次调用读取文件的一个字符
fputc将一个字符写入文件int fputc(int c, FILE *stream);写入的字符或 EOF每次调用写入文件的一个字符
fgets从文件中读取一行文本char *fgets(char *str, int n, FILE *stream);读取的文本或 NULL每次调用读取文件的一行文本
fputs将一行文本写入文件int fputs(const char *str, FILE *stream);写入的字节数或 EOF每次调用写入文件的一行文本
fscanf读取文件并转换成变量int fscanf(FILE *stream, const char *format, ...);读取并转换的输入项数根据格式字符串读取文件并转换成变量
fprintf将变量格式化后写入文件int fprintf(FILE *stream, const char *format, ...);写入的字节数根据格式字符串将变量写入文件
fread从文件中读取数据size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);读取的字节数或 EOF每次调用读取指定数量的字节
fwrite将数据写入文件size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);写入的字节数每次调用写入指定数量的字节
eg 1: 使用 fgetc 读取文件中的一个字符
#include <stdio.h>
int main() {
    FILE *fp;
    char ch;
    fp = fopen("data.txt", "r"); // 打开文件用于读取
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    ch = fgetc(fp); // 读取文件中的第一个字符
    printf("Read character: %c\n", ch);
    fclose(fp); // 关闭文件
    return 0;
}

eg 2: 使用 fgets 读取文件中的一行文本

#include <stdio.h>
int main() {
    FILE *fp;
    char buffer[100];
    fp = fopen("data.txt", "r"); // 打开文件用于读取
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    fgets(buffer, 100, fp); // 读取文件中的一行文本
    printf("Read line: %s\n", buffer);
    fclose(fp); // 关闭文件
    return 0;
}

eg 3: 使用 fwrite 写入数据到文件

#include <stdio.h>
int main() {
    FILE *fp;
    int data[] = {1, 2, 3, 4, 5};
    size_t bytes_written;
    fp = fopen("data.bin", "wb"); // 打开文件用于写入
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    bytes_written = fwrite(data, sizeof(int), 5, fp); // 写入数据到文件
    printf("Written bytes: %zu\n", bytes_written);
    fclose(fp); // 关闭文件
    return 0;
}

每个例子都包含了打开文件、执行读写操作和关闭文件的步骤。这些例子展示了如何在 C 语言中使用这些基本的文件操作函数。

文件的随机读写

文件的随机读写是指可以读取或写入文件中的任意位置的数据,而不必按照文件的顺序进行。随机读写函数允许你直接跳转到文件中的特定位置,读取或写入一个或多个字节。以下是一些常用的文件随机读写函数。
在 C 语言中,文件的随机读写是指可以读取或写入文件中的任意位置的数据,而不必按照文件的顺序进行。随机读写函数允许你直接跳转到文件中的特定位置,读取或写入一个或多个字节。以下是一些常用的文件随机读写函数:

文件随机读取函数

  1. fseek
    int fseek(FILE *stream, long int offset, int whence);
    
    fseek 函数用于设置文件的读/写位置。stream 参数是指向 FILE 对象的指针,offset 是一个长整型数,表示从 whence 指定的位置开始的偏移量。whence 参数可以是 SEEK_SET(文件开头)、SEEK_CUR(当前位置)或 SEEK_END(文件末尾)。函数返回 0 表示成功,或者返回 -1 表示失败。
  2. ftell
    long int ftell(FILE *stream);
    
    ftell 函数用于获取当前文件的读/写位置。函数返回当前位置相对于文件开头的偏移量,如果出错,返回 -1
  3. fgetc(用于随机读取)
    int fgetc(FILE *stream);
    
    fgetc 函数用于读取文件的一个字符。为了实现随机读取,你首先需要使用 fseek 函数将文件指针移动到想要读取的位置。

文件随机写入函数

  1. fputc(用于随机写入)
    int fputc(int c, FILE *stream);
    
    fputc 函数用于写入文件的一个字符。为了实现随机写入,你首先需要使用 fseek 函数将文件指针移动到想要写入的位置。
  2. fwrite
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    
    fwrite 函数用于向文件中写入数据。为了实现随机写入,你首先需要使用 fseek 函数将文件指针移动到想要写入的位置。

示例代码

以下是一个简单的示例,展示了如何使用 fseekfwrite 函数进行文件的随机写入:

#include <stdio.h>
int main() {
    FILE *fp;
    int data[] = {1, 2, 3, 4, 5};
    size_t bytes_written;
    fp = fopen("data.bin", "w+b"); // 打开文件用于写入和读取
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 将文件指针移动到文件末尾
    fseek(fp, 0, SEEK_END);
    // 写入数据到文件末尾
    bytes_written = fwrite(data, sizeof(int), 5, fp);
    printf("Written bytes: %zu\n", bytes_written);
    // 关闭文件
    fclose(fp);
    return 0;
}

在上面的示例中,我们使用了 fseek 函数将文件指针移动到文件末尾,然后使用 fwrite 函数向文件末尾写入数据。这样可以实现文件的随机写入操作。

rewind 函数

用于将文件指针重新定位到文件的开始位置。这个函数非常有用,当你想要从头开始重新读取一个文件时,而不想从头开始逐字节移动文件指针。以下是 rewind 函数的原型:

void rewind(FILE *stream);

rewind 函数接受一个指向 FILE 对象的指针 stream,表示要重置的文件流。调用 rewind 函数后,文件指针将移动到文件的开头,就像文件刚刚被打开一样。
下面是一个使用 rewind 函数的示例:

#include <stdio.h>
int main() {
    FILE *fp;
    int ch;
    fp = fopen("data.txt", "r"); // 打开文件用于读取
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 读取文件的一个字符
    ch = fgetc(fp);
    printf("Read character: %c\n", ch);
    // 将文件指针重新定位到文件开始位置
    rewind(fp);
    // 重新读取文件的一个字符
    ch = fgetc(fp);
    printf("Rewinded and read character: %c\n", ch);
    // 关闭文件
    fclose(fp);
    return 0;
}

在上述示例中,我们首先读取了文件 data.txt 的一个字符,然后调用了 rewind 函数将文件指针重新定位到文件的开头。之后,我们再次读取了文件的一个字符。由于 rewind 函数的作用,第二次读取的是文件开头的同一个字符。
rewind 函数通常用于数据处理任务,比如当你需要对文件进行多次读取操作,并且每次都需要从文件开始处读取时,使用 rewind 函数可以简化代码,避免手动移动文件指针的复杂性。

文件读取结束的判定

在 C 语言中,文件操作是编程中的一个常见任务。当我们读取文件时,我们需要一种方法来确定何时我们已经到达文件的末尾。这里,我们要讨论的是如何使用 feof 函数来帮助我们判断文件是否已经读取完毕。
首先,我们需要明确一点:feof 函数并不直接告诉我们文件是否结束,而是告诉我们文件指针是否已经到达文件末尾。这意味着,即使 feof 返回 1,文件也可能还有数据,只是文件指针已经超出了数据区域。因此,我们不能仅仅依赖 feof 的返回值来判断文件是否结束。
正确的方法是,在每次读取操作之后,检查读取函数的返回值。例如,当我们使用 fgetcfgets 读取文件时,如果文件已经读取完毕,fgetc 会返回 EOF(End Of File),而 fgets 会返回一个空字符串(\0)。这样,我们就可以确定文件是否已经读取完毕。
下面是一个示例,展示了如何正确使用 fgetcfeof

#include <stdio.h>
int main() {
    FILE *fp;
    int ch;
    fp = fopen("data.txt", "r"); // 打开文件用于读取
    if (fp == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 逐字符读取文件
    while ((ch = fgetc(fp)) != EOF) {
        printf("Read character: %c\n", ch);
    }
    // 检查是否到达文件末尾
    if (feof(fp)) {
        printf("Reached end of file due to EOF.\n");
    } else {
        printf("Did not reach end of file.\n");
    }
    // 关闭文件
    fclose(fp);
    return 0;
}

在这个示例中,我们使用 while 循环逐字符读取文件。每次 fgetc 函数读取一个字符后,我们检查返回值是否为 EOF。如果是,我们使用 feof 函数来确认是否已经到达文件末尾。如果 feof 返回 1,我们输出 “Reached end of file due to EOF.”;如果返回 0,我们输出 “Did not reach end of file.”。
这样,我们就通过正确的逻辑来判断文件是否读取结束,而不是直接依赖 feof 的返回值。这种方法可以确保我们在文件末尾正确地处理数据,而不会错误地认为文件中还有未读取的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值