引文
这是一个简单的存储学生数据函数:
// 函数: save_record()
// 功能: 保存学生数据到文件中
void save_record()
{
FILE* fp; // 声明一个文件指针
int i; // 声明一个整型变量用于循环计数
// 尝试以二进制写模式打开文件 "student-list"
if ((fp = fopen("student-list", "wb")) == NULL)
{
printf("cannot open file\n"); // 如果打开失败,输出错误信息
return; // 并退出函数
}
// fwrite()函数的第一个参数应该是要写入的数据的地址
// 这里假设 'h' 是一个整型变量,存储了学生人数
// 写入学生人数到文件中
fwrite(&h, sizeof(int), 1, fp);
// 遍历学生数组
for (i = 0; i < h; i++)
{
// 尝试将当前学生的数据写入文件
// 's' 应该是一个结构体数组,每个元素都是一个学生的信息
if (fwrite(&s[i], sizeof(struct student), 1, fp) != 1)
{
printf("file write error\n"); // 如果写入失败,输出错误信息
}
else
{
printf("file write sucess\n"); // 如果成功,输出成功信息
}
}
// 关闭文件
fclose(fp);
}
这里出现了几个文件操作的函数fopen()、fwrite()、fclose(),还有一个文件指针。
整个函数save_record()的作用不再赘述,注释很清楚。
在我们初识c语言且在接触文件操作之前,它就像是一滩史莱姆在cup 内存 储存之间 不断流转。似乎不会影响本地计算机的运作,将其进程终结,从储存中擦去程序,它将不留一丝痕迹。但文件操作让它有了“自我繁殖”能力和更长的生命。
先知道如何使用C语言进行文件操作
C语言提供了强大的文件处理功能,这主要通过标准I/O库(stdio.h)中的函数实现。在C语言中,文件被视为流,可以被打开、读取、写入、定位和关闭。
基础概念:
在C语言中,文件通常被分类为文本文件和二进制文件:
- 文本文件:由字符序列组成,适合人类阅读,每个字符都解释为ASCII或Unicode码。
- 二进制文件:直接保存内存中的字节序列,可能包含无法显示的字符
文件操作步骤:
- 打开文件:使用fopen()函数。
- 读写文件:使用fread(), fwrite(), fgetc(), fputc(), fgets(), fputs(),
fprintf(), fscanf()等函数。 - 关闭文件:使用fclose()函数。
函数使用详解:
fopen()
fopen()函数是C语言中用于打开文件或创建新文件的标准库函数。这个函数允许你指定文件的名称以及访问模式。
FILE *fopen(const char *path, const char *mode);
参数:
- path:一个字符串,表示要打开的文件的路径和名称。
- mode:一个字符串,表示文件的打开模式。常见的模式有:
“r”:只读模式。如果文件不存在,则会返回NULL。
“w”:写入模式。如果文件存在则会被清空,如果文件不存在则会被创建。
“a”:追加模式。如果文件不存在则会被创建,如果存在则文件指针会放在文件末尾。
“r+”:读写模式。如果文件不存在,则会返回NULL。
“w+”:读写模式。如果文件存在则会被清空,如果文件不存在则会被创建。
“a+”:读写模式。如果文件不存在则会被创建,如果存在则文件指针会放在文件末尾。
“rb”、“wb”、“ab”、“r+b”、“w+b”、“a+b”:与上述模式相同,但以二进制形式打开文件。
返回值:
- 如果函数调用成功,fopen()会返回一个指向FILE结构体的指针,这个结构体包含了文件的相关信息,如文件的位置和其他状态信息。
- 如果文件无法打开或者创建失败,fopen()会返回NULL。此时,可以通过调用perror()函数来显示系统错误消息,或通过errno宏来检查具体的错误代码。
注意事项:
- 在使用完文件后,应该使用fclose()函数关闭文件,以释放系统资源。
- 在打开文件时,始终检查fopen()的返回值是否为NULL,以确保文件被正确打开。
- 当使用"w"或"w+"模式打开文件时,现有的文件内容会被清空。
- 使用"a"或"a+"模式打开文件时,文件指针会被定位到文件的末尾,因此任何写入操作都会发生在文件的末尾。
fread(), fwrite()
fread()和fwrite()是C语言中用于文件读写操作的重要函数,它们允许你以二进制模式读写任意类型的数据,而不仅仅是字符或字符串。
size_t 类型它是特别为表示大小和计数设计的一种无符号整数类型。size_t 并不是一个基本类型,而是由 <stddef.h> 头文件定义的一个typedef。size_t 的确切类型(比如 unsigned int、unsigned long 或者其他类型)取决于实现和编译器,但它总是能够表示任何对象的大小。
- fread() 函数
fread()函数从文件中读取数据到一个预分配的内存块中。函数原型如下:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数
- ptr:指向一个内存块的指针,数据将被读入到该内存块中。
- size:每个元素的大小(以字节为单位)。
- count:要读取的元素数量。
- stream:一个FILE *类型的指针,指向要读取的文件。
返回值
返回实际读取的元素数量。如果返回值小于count,则可能是因为到达了文件末尾或读取过程中出现了错误。
- fwrite() 函数
fwrite()函数将数据从内存块写入到文件中。函数原型如下:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
参数
- ptr:指向一个内存块的指针,数据将从该内存块中读出并写入文件。
- size:每个元素的大小(以字节为单位)。
- count:要写入的元素数量。
- stream:一个FILE *类型的指针,指向要写入的文件。
返回值
返回实际写入的元素数量。如果返回值小于count,则可能是因为写入过程中出现了错误。
演示代码
#include <stdio.h>
#define BUFFER_SIZE 100
int main() {
FILE *source_file, *dest_file;
int buffer[BUFFER_SIZE];
size_t items_read, items_written;
// 打开源文件和目标文件
source_file = fopen("source.dat", "rb");
dest_file = fopen("destination.dat", "wb");
// 检查文件是否成功打开
if (source_file == NULL || dest_file == NULL) {
perror("Error opening files");
return 1;
}
// 读取数据
items_read = fread(buffer, sizeof(int), BUFFER_SIZE, source_file);
printf("Read %zu items.\n", items_read);
// 写入数据
items_written = fwrite(buffer, sizeof(int), items_read, dest_file);
printf("Wrote %zu items.\n", items_written);
// 关闭文件
fclose(source_file);
fclose(dest_file);
return 0;
}
在这个示例中,我们首先打开两个文件,一个用于读取,另一个用于写入。然后,我们定义了一个整型数组作为缓冲区,使用fread()从源文件中读取数据到缓冲区,再使用fwrite()将缓冲区中的数据写入到目标文件中。最后,我们关闭所有打开的文件。
注意,在使用fread()和fwrite()时,确保文件是以二进制模式打开的(使用"rb"或"wb"模式)。这样可以保证跨平台的兼容性,避免因换行符转换等问题导致的数据损坏。
fgetc(), fputc(), fgets(), 和 fputs()
- fgetc()
fgetc() 函数从文件流中读取一个字符。如果文件没有到达 EOF(文件结束标志),函数将返回读取的字符的 ASCII 值;如果到达 EOF 或者读取时出现错误,函数将返回 EOF(通常定义为 -1)。
函数原型
int fgetc(FILE *stream);
- fputc()
fputc() 函数将一个字符写入到文件流中。如果写入成功,函数将返回写入的字符的 ASCII 值;如果写入失败,函数将返回 EOF。
函数原型
int fputc(int c, FILE *stream);
- fgets()
fgets() 函数从文件流中读取一行文本,最多读取 n-1 个字符(n 由第二个参数指定),并以 null 字符终止。如果遇到换行符或文件结束标志 EOF,读取操作将停止。读取到的换行符也会被存储在缓冲区中,除非读取的字符总数已经达到 n-1。
函数原型
char *fgets(char *s, int n, FILE *stream);
- fputs()
fputs() 函数将一个字符串写入到文件流中。字符串以 null 字符终止,但是 null 字符本身不会被写入文件。
函数原型
int fputs(const char *s, FILE *stream);
示例代码
#include <stdio.h>
#include <string.h>
int main() {
FILE *file;
char line[100];
int ch;
// 打开文件
file = fopen("example.txt", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
// 使用 fgetc() 读取单个字符
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
// 使用 fgets() 读取一行
if (fgets(line, sizeof(line), file) != NULL) {
printf("Read line: %s", line);
}
// 关闭文件
fclose(file);
// 创建文件并使用 fputc() 和 fputs() 写入数据
file = fopen("output.txt", "w");
if (file == NULL) {
perror("Error opening file");
return 1;
}
// 写入单个字符
fputc('H', file);
fputc('e', file);
fputc('l', file);
fputc('l', file);
fputc('o', file);
fputc('\n', file);
// 写入字符串
fputs("World\n", file);
// 关闭文件
fclose(file);
return 0;
}
在这个示例中,我们首先打开了一个文件 example.txt,使用 fgetc() 读取并打印每个字符,然后使用 fgets() 读取并打印一行文本。接下来,我们创建了一个新的文件 output.txt,使用 fputc() 和 fputs() 分别写入单个字符和字符串。最后关闭所有打开的文件。
fclose()
fclose() 是一个在 C 语言标准库中用于关闭已打开文件的函数。当你使用诸如 fopen() 或 freopen() 函数打开一个文件并完成对文件的操作后,你应该调用 fclose() 来释放与该文件相关的所有资源。
int fclose(FILE *stream);
返回值
如果文件成功关闭,fclose() 返回 0;如果发生错误(例如,如果文件正在被另一个进程使用),则返回 EOF(即 -1)。在调用 fclose() 后,你不能再通过相同的 FILE 指针访问该文件,直到再次打开它。
这是因为 fclose() 不仅关闭了文件,还释放了与之关联的所有资源,包括缓冲区和底层的文件描述符。这意味着 FILE 结构体中的信息不再有效,如果你尝试再次使用这个指针,结果是未定义的,可能会导致程序崩溃或其他错误行为。
如果你想再次使用同一个文件,你需要重新打开它,通常使用 fopen() 或者 freopen() 函数。这将创建一个新的 FILE 结构体,你可以使用新的指针来进行读写操作。
持续施工。。。。。。