C 语言文件处理
C 语言文件处理
C 语言文件处理是指使用 C 语言函数执行文件操作(例如创建、打开、写入数据、读取数据、重命名和删除)的过程。借助这些函数,我们可以在程序中执行文件操作,在文件中存储和检索数据。
C 语言文件处理的必要性
如果我们使用 C 语言程序执行输入和输出操作,则只要程序运行,数据就会存在;程序终止后,我们就无法再次使用该数据。文件处理用于处理存储在外部存储器中的文件,即在计算机的外部存储器中存储和访问信息。您可以使用文件处理永久保存数据。
文件类型
文件表示一个字节序列。文件有两种类型:文本文件和二进制文件 -
- 文本文件 - 文本文件以 ASCII 字符的形式包含数据,通常用于存储字符流。文本文件中的每一行都以换行符(" ")结尾,并且通常以".txt"为扩展名。
- 二进制文件 - 二进制文件以原始位(0 和 1)的形式包含数据。不同的应用程序对位和字节的表示方式不同,并使用不同的文件格式。图像文件(.png、.jpg)、可执行文件(.exe、.com)等都是二进制文件的示例。
FILE 指针 (File*)
使用文件处理时,需要一个文件指针来存储 fopen() 函数返回的 FILE 结构的引用。所有文件处理操作都需要该文件指针。
fopen() 函数返回一个 FILE 类型的指针。 FILE 是 stdio.h 中预定义的结构体类型,包含文件描述符、大小、位置等属性。
typedef struct { int fd; /* 文件描述符 */ unsigned char *buf; /* 缓冲区 */ size_t size; /* 文件大小 */ size_t pos; /* 文件中的当前位置 */ } FILE;
声明文件指针 (FILE*)
以下是声明文件指针的语法 -
FILE* file_pointer;
打开(创建)文件
任何操作都必须打开文件。fopen() 函数用于创建新文件或打开现有文件。您需要指定要打开的模式。下文介绍了各种文件打开模式,创建/打开文件时可以使用其中任何一种。
fopen() 函数返回一个 FILE 指针,该指针可用于其他操作,例如读取、写入和关闭文件。
语法
以下是打开文件的语法 -
FILE *fopen(const char *filename, const char *mode);
其中,filename 是要打开的文件的名称,mode 定义文件的打开模式。
文件打开模式
默认情况下,文件访问模式以文本或 ASCII 模式打开文件。如果您要处理二进制文件,则应使用以下访问模式,而不是上述模式:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
文件可以使用多种模式打开。以下是不同的文件打开模式 -
模式 | 描述 |
---|---|
r | 打开现有文本文件进行读取。 |
w | 打开文本文件进行写入。如果文件不存在,则创建一个新文件。此处,程序将从文件开头开始写入内容。 |
a | 以追加模式打开一个文本文件进行写入。如果文件不存在,则创建一个新文件。此处,程序将开始在现有文件内容中追加内容。 |
r+ | 打开一个文本文件进行读写操作。 |
打开一个文本文件进行读写操作。如果文件存在,则首先将其长度截断为零;如果文件不存在,则创建一个文件。 | |
a+ | 打开一个文本文件进行读写操作。如果文件不存在,则创建该文件。读取操作将从头开始,但写入操作只能追加。 |
创建文件示例
在下面的示例中,我们将创建一个新文件。创建新文件的文件模式为"w"(写入模式)。
#include <stdio.h> int main() { FILE * file; // 创建文件 file = fopen("file1.txt", "w"); // 检查文件是否已创建 if (file == NULL) { printf("Error in creating file"); return 1; } printf("File created."); return 0; }
输出
File created.
打开文件示例
以下示例中,我们将打开一个现有文件。打开现有文件的文件模式为"r"(只读)。您也可以使用上面介绍的其他文件打开模式选项。
注意:必须有一个要打开的文件。
#include <stdio.h> int main() { FILE * file; // 打开文件 file = fopen("file1.txt", "r"); // 检查文件是否已打开 if (file == NULL) { printf("Error in opening file"); return 1; } printf("File opened."); return 0; }
输出
File opened.
关闭文件
每个文件在执行操作后都必须关闭。fclose() 函数 用于关闭已打开的文件。
语法
以下是 fclose() 函数的语法 -
int fclose(FILE *fp);
fclose() 函数在成功时返回零,如果关闭文件时出错,则返回 EOF。
fclose() 函数实际上会将缓冲区中所有待处理的数据刷新到文件中,关闭文件并释放文件占用的内存。 EOF 是头文件 stdio.h 中定义的常量。
关闭文件示例
在以下示例中,我们将关闭一个打开的文件 -
#include <stdio.h> int main() { FILE * file; // 打开文件 file = fopen("file1.txt", "w"); // 检查文件是否已打开 // 是否已打开 if (file == NULL) { printf("Error in opening file"); return 1; } printf("File opened."); // 关闭文件 fclose(file); printf(" File closed."); return 0; }
输出
File opened. File closed.
写入文本文件
以下库函数用于将数据写入以可写模式打开的文件中 -
- fputc():将单个字符写入文件。
- fputs():将字符串写入文件。
- fprintf():将格式化的字符串(数据)写入文件。
将单个字符写入文件
fputc() 函数是一个非格式化函数,它将参数"c"的单个字符值写入"fp"引用的输出流。
int fputc(int c, FILE *fp);
示例
以下代码将给定字符数组中的一个字符写入以"w"模式打开的文件中:
#include <stdio.h> int main() { FILE *fp; char * string = "C Programming tutorial from TutorialsPoint"; int i; char ch; fp = fopen("file1.txt", "w"); for (i = 0; i < strlen(string); i++) { ch = string[i]; if (ch == EOF) break; fputc(ch, fp); } printf (" "); fclose(fp); return 0; }
输出
After executing the program, "file1.txt" will be created in the current folder and the string is written to it.
将字符串写入文件
fputs() 函数将字符串"s"写入"fp"引用的输出流。成功时返回非负值,否则返回 EOF(文件尾)。
int fputs(const char *s, FILE *fp);
示例
以下程序将给定二维 char 数组中的字符串写入文件 -
#include <stdio.h> int main() { FILE *fp; char *sub[] = {"C Programming Tutorial ", "C++ Tutorial ", "Python Tutorial ", "Java Tutorial "}; fp = fopen("file2.txt", "w"); for (int i = 0; i < 4; i++) { fputs(sub[i], fp); } fclose(fp); return 0; }
输出
程序运行时,在当前文件夹中创建一个名为"file2.txt"的文件并保存以下行 -
C Programming Tutorial C++ Tutorial Python Tutorial Java Tutorial
将格式化字符串写入文件
fprintf() 函数将格式化的数据流发送到 FILE 指针所指向的磁盘文件。
int fprintf(FILE *stream, const char *format [, argument, ...])
示例
在下面的程序中,我们有一个名为"employee"的结构体类型数组。该结构体包含一个字符串、一个整数和一个浮点数元素。使用 fprintf() 函数将数据写入文件。
#include <stdio.h> struct employee { int age; float percent; char *name; }; int main() { FILE *fp; struct employee emp[] = { {25, 65.5, "Ravi"}, {21, 75.5, "Roshan"}, {24, 60.5, "Reena"} }; char *string; fp = fopen("file3.txt", "w"); for (int i = 0; i < 3; i++) { fprintf(fp, "%d %f %s ", emp[i].age, emp[i].percent, emp[i].name); } fclose(fp); return 0; }
输出
When the above program is executed, a text file is created with the name "file3.txt" that stores the employee data from the struct array.
从文本文件读取
以下库函数可用于从以读取模式打开的文件中读取数据 -
- fgetc():从文件中读取单个字符。
- fgets():从文件中读取字符串。
- fscanf():从文件中读取格式化字符串。
从文件中读取单个字符
fgetc() 函数从"fp"引用的输入文件中读取一个字符。返回值是读取到的字符,如果发生任何错误,则返回 EOF。
int fgetc(FILE * fp);
示例
以下示例逐个字符地读取给定文件,直至到达文件末尾。
#include <stdio.h> int main(){ FILE *fp ; char ch ; fp = fopen ("file1.txt", "r"); while(1) { ch = fgetc (fp); if (ch == EOF) break; printf ("%c", ch); } printf (" "); fclose (fp); }
输出
运行代码并检查其输出 −
C Programming tutorial from TutorialsPoint
从文件读取字符串
fgets() 函数从"fp"引用的输入流中读取最多"n 1"个字符。它将读取的字符串复制到缓冲区"buf"中,并在其后附加一个空字符以终止字符串。
示例
以下程序读取给定文件中的每一行,直到检测到文件末尾为止 -
# include <stdio.h> int main() { FILE *fp; char *string; fp = fopen ("file2.txt", "r"); while (!feof(fp)) { fgets(string, 256, fp); printf ("%s", string) ; } fclose (fp); }
输出
运行代码并检查其输出 −
C Programming Tutorial C++ Tutorial Python Tutorial Java Tutorial
从文件读取格式化字符串
C 语言中的 fscanf() 函数 用于从文件读取格式化输入。
int fscanf(FILE *stream, const char *format, ...)
示例
在下面的程序中,我们使用 fscanf() 函数读取不同类型变量中的格式化数据。常用的格式说明符用于指示字段类型(%d、%f、%s 等)。
#include <stdio.h> int main() { FILE *fp; char *s; int i, a; float p; fp = fopen ("file3.txt", "r"); if (fp == NULL) { puts ("Cannot open file"); return 0; } while (fscanf(fp, "%d %f %s", &a, &p, s) != EOF) printf ("Name: %s Age: %d Percent: %f ", s, a, p); fclose(fp); return 0; }
输出
上述程序执行后,会打开文本文件"file3.txt",并将其内容打印在屏幕上。运行代码后,您将获得如下输出:
Name: Ravi Age: 25 Percent: 65.500000 Name: Roshan Age: 21 Percent: 75.500000 Name: Reena Age: 24 Percent: 60.500000
文件处理二进制读写函数
对于二进制文件,读写操作以二进制形式进行。您需要在访问模式中包含字符"b"(写入二进制文件时使用"wb",读取二进制文件时使用"rb")。
有两个函数可用于二进制输入和输出:fread() 函数和 fwrite() 函数。这两个函数都可用于读写内存块,通常是数组或结构体。
写入二进制文件
fwrite() 函数将指定的字节块从缓冲区写入以二进制写入模式打开的文件。以下是该函数的原型:
fwrite(*buffer, size, no, FILE);
示例
在下面的程序中,声明了一个名为"employee"的结构体类型数组。我们使用 fwrite() 函数将一个字节块(大小相当于一个 employee 数据)写入以"wb"模式打开的文件中。
#include <stdio.h> struct employee { int age; float percent; char name[10]; }; int main() { FILE *fp; struct employee e[] = { {25, 65.5, "Ravi"}, {21, 75.5, "Roshan"}, {24, 60.5, "Reena"} }; char *string; fp = fopen("file4.dat", "wb"); for (int i = 0; i < 3; i++) { fwrite(&e[i], sizeof (struct employee), 1, fp); } fclose(fp); return 0; }
输出
When the above program is run, the given file will be created in the current folder. It will not show the actual data, because the file is in binary mode.
读取二进制文件
fread() 函数 从以二进制读取模式打开的文件中读取指定大小的字节块,并将其保存到指定大小的缓冲区中。以下是该函数的原型:
fread(*buffer, size, no, FILE);
示例
在下面的程序中,声明了一个名为"employee"的结构体类型数组。我们使用 fread() 函数从以"rb"模式打开的文件中读取一个字节块,该字节块的大小相当于一个 employee 数据的大小。
#include <stdio.h> struct employee { int age; float percent; char name[10]; }; int main() { FILE *fp; struct employee e; fp = fopen ("file4.dat", "rb"); if (fp == NULL) { puts ("Cannot open file"); return 0; } while (fread (&e, sizeof (struct employee), 1, fp) == 1) printf ("Name: %s Age: %d Percent: %f ", e.name, e.age, e.percent); fclose(fp); return 0; }
输出
上述程序执行后,会打开文件"file4.dat",并将其内容打印在屏幕上。运行代码后,您将获得如下输出:
Name: Ravi Age: 25 Percent: 65.500000 Name: Roshan Age: 21 Percent: 75.500000 Name: Reena Age: 24 Percent: 60.500000
重命名文件
rename() 函数用于将现有文件从旧文件名重命名为新文件名。
语法
以下是重命名文件的语法 -
int rename(const char *old_filename, const char *new_filename)
示例
#include <stdio.h> int main() { // 旧文件名和新文件名 char * file_name1 = "file1.txt"; char * file_name2 = "file2.txt"; // 将旧文件名重命名为新文件名 if (rename(file_name1, file_name2) == 0) { printf("File renamed successfully. "); } else { perror("There is an error."); } return 0; }
输出
如果有可用的文件(file1.txt),则输出如下 -
Name: Ravi Age: 25 Percent: 65.500000 Name: Roshan Age: 21 Percent: 75.500000 Name: Reena Age: 24 Percent: 60.500000