1. fopen
— 打开文件
函数原型:
FILE *fopen(const char *filename, const char *mode);
参数:
-
filename
:要打开的文件名,可以是相对路径或绝对路径。 -
mode
:文件打开模式,表示文件的操作方式(如只读、写入、追加等)。
常见的打开模式:
-
"r"
:只读模式,文件必须存在。 -
"w"
:只写模式,如果文件存在会清空文件,不存在则创建。 -
"a"
:追加模式,文件不存在则创建,写入时数据会追加到文件末尾。 -
"r+"
:读写模式,文件必须存在。 -
"w+"
:读写模式,文件存在则清空,不存在则创建。 -
"a+"
:读写模式,文件不存在则创建,数据追加到文件末尾。
返回值:
-
如果成功,返回一个指向文件的指针(
FILE *
)。 -
如果失败,返回
NULL
,通常使用perror()
或errno
获取错误信息。
示例:
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {perror("无法打开文件");return 1;
}
注意事项:
-
fopen
只支持文本文件和二进制文件的打开,打开方式非常灵活,可以通过不同的模式选择合适的文件操作。 -
打开文件后,应确保及时关闭文件,使用
fclose()
。 -
fopen
函数会自动创建文件指针,并为文件分配缓冲区。
2. fread
— 从文件读取数据
函数原型:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数:
-
ptr
:指向要存储读取数据的内存缓冲区。 -
size
:每个元素的字节数(通常为sizeof(type)
)。 -
count
:要读取的元素数量。 -
stream
:文件指针,表示要读取的文件。
返回值:
-
返回实际读取的元素数量。如果返回值小于
count
,表示可能发生了错误或到达了文件末尾(EOF
)。
示例:
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {perror("无法打开文件");return 1;
}char buffer[100];
size_t bytesRead = fread(buffer, sizeof(char), sizeof(buffer), fp);
if (bytesRead > 0) {printf("读取到的内容: %s\n", buffer);
}
fclose(fp);
注意事项:
-
fread
是基于缓冲区的读取,性能较高,适合读取大块数据。 -
读取时要确保
ptr
的内存空间足够容纳读取的数据。 -
fread
适用于二进制数据的读取。如果是读取文本数据,最好使用fgets
。 -
fread
读取时并不会自动添加字符串终止符\0
,如果读取的是字符串,需手动添加。
3. fwrite
— 向文件写入数据
函数原型:
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
参数:
-
ptr
:指向要写入的数据的内存缓冲区。 -
size
:每个元素的字节数(通常为sizeof(type)
)。 -
count
:要写入的元素数量。 -
stream
:文件指针,表示要写入的文件。
返回值:
-
返回实际写入的元素数量。如果返回值小于
count
,表示可能发生了错误。
示例:
FILE *fp = fopen("output.txt", "w");
if (fp == NULL) {perror("无法打开文件");return 1;
}const char *data = "Hello, World!";
size_t bytesWritten = fwrite(data, sizeof(char), strlen(data), fp);
if (bytesWritten != strlen(data)) {perror("写入文件失败");
}
fclose(fp);
注意事项:
-
fwrite
会自动使用缓冲区,提高性能。 -
使用
fwrite
时应确保数据类型和缓冲区大小正确。通常用于写入二进制数据。 -
fwrite
也不会在写入的数据末尾自动添加字符串结束符\0
,需根据实际需求手动处理。
4. fseek
— 设置文件指针的位置
函数原型:
int fseek(FILE *stream, long int offset, int whence);
参数:
-
stream
:文件指针。 -
offset
:从whence
指定的起始位置开始的偏移量。 -
whence
:起始位置的标志,常用的值包括:-
SEEK_SET
:文件开头。 -
SEEK_CUR
:当前位置。 -
SEEK_END
:文件末尾。
-
返回值:
-
成功时返回 0,失败时返回非零值。
示例:
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {perror("无法打开文件");return 1;
}fseek(fp, 0, SEEK_END); // 定位到文件末尾
long fileSize = ftell(fp); // 获取文件大小
printf("文件大小: %ld 字节\n", fileSize);fseek(fp, 0, SEEK_SET); // 重置文件指针到文件开头
fclose(fp);
注意事项:
-
fseek
可以改变文件指针的位置,在读取或写入时可以灵活地控制文件位置。 -
fseek
和ftell
配合使用,能够实现文件大小的获取。 -
使用时要注意文件是否已正确打开,并且文件指针的偏移量是否合理。
5. fclose
— 关闭文件
函数原型:
int fclose(FILE *stream);
参数:
-
stream
:要关闭的文件指针。
返回值:
-
成功时返回 0,失败时返回 EOF。
示例:
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {perror("无法打开文件");return 1;
}fclose(fp); // 关闭文件
注意事项:
-
必须关闭文件:每次打开文件后,使用完文件后必须调用
fclose()
关闭文件,释放资源。 -
fclose()
会刷新文件的缓冲区,如果有未写入的数据,会被强制写入文件。 -
在程序结束时忘记关闭文件可能会导致内存泄漏或资源占用。
6. fputc
— 向文件写入一个字符
函数原型:
int fputc(int character, FILE *stream);
参数:
-
character
:要写入的字符。注意,这里传入的是一个整数类型(通常是char
的 ASCII 值),而不是字符本身,因此需要使用字符类型转换。 -
stream
:文件指针,指向目标文件。
返回值:
-
如果写入成功,返回写入的字符(转换为
unsigned char
)。 -
如果写入失败,返回
EOF
。
示例:
#include <stdio.h>int main() {FILE *fp = fopen("example.txt", "w");if (fp == NULL) {perror("无法打开文件");return 1;}fputc('H', fp); // 向文件中写入字符 'H'fputc('i', fp); // 向文件中写入字符 'i'fclose(fp); // 关闭文件return 0;
}
注意事项:
-
fputc
只能写入单个字符。写入多个字符时,需要多次调用fputc
。 -
fputc
写入时不会自动添加换行符,必须手动写入(如fputc('\n', fp)
)。 -
如果写入过程中发生错误,
fputc
返回EOF
,可以通过perror
或检查文件指针的状态进行处理。
7. fgetc
— 从文件读取一个字符
函数原型:
int fgetc(FILE *stream);
参数:
-
stream
:文件指针,指向要读取的文件。
返回值:
-
成功时,返回读取的字符(以
unsigned char
形式返回,但作为int
类型)。 -
如果读取到文件结束符(
EOF
),返回EOF
。 -
如果发生读取错误,也会返回
EOF
。
示例:
#include <stdio.h>int main() {FILE *fp = fopen("example.txt", "r");if (fp == NULL) {perror("无法打开文件");return 1;}int ch;while ((ch = fgetc(fp)) != EOF) { // 逐个字符读取文件内容putchar(ch); // 输出字符}fclose(fp); // 关闭文件return 0;
}
注意事项:
-
fgetc
一次读取一个字符,适用于逐字符读取文件。 -
在读取时,
fgetc
会返回字符的 ASCII 值。如果遇到文件结束符(EOF
),则停止读取。 -
使用
fgetc
时要注意检查返回值,EOF
可能意味着文件结束或读取错误,因此应及时检查并处理。
8. feof
— 检查是否到达文件末尾
函数原型:
int feof(FILE *stream);
参数:
-
stream
:文件指针,指向要检查的文件。
返回值:
-
如果文件指针已到达文件末尾,返回非零值(通常是
1
)。 -
如果文件指针尚未到达文件末尾,返回
0
。
示例:
#include <stdio.h>int main() {FILE *fp = fopen("example.txt", "r");if (fp == NULL) {perror("无法打开文件");return 1;}int ch;while ((ch = fgetc(fp)) != EOF) {putchar(ch); // 输出字符}if (feof(fp)) {printf("\n已到达文件末尾。\n");}fclose(fp); // 关闭文件return 0;
}
注意事项:
-
feof
在文件读取时用来检查是否已到达文件末尾,它不会主动读取文件内容,因此最好在文件读取后使用(如通过fgetc
或fread
等函数)。 -
不要在
fgetc
、fread
等读取函数调用前检查feof
,因为feof
只能判断是否到达文件末尾,而不是预测读取是否成功。正确的做法是在读取失败或读取结束后再检查feof
。
总结
-
fopen
:用于打开文件,返回文件指针,可以设置文件的打开模式。 -
fread
:用于从文件中读取数据,适用于读取二进制数据。 -
fwrite
:用于将数据写入文件,适用于写入二进制数据。 -
fseek
:用于设置文件指针的位置,可以在文件内部进行定位。 -
fclose
:关闭文件,释放资源,确保数据写入完成。 -
fputc
:用于写入单个字符,适合逐个字符地写入文件。如果要写入多个字符,可以多次调用fputc
,或者使用fwrite
。 -
fgetc
:用于读取单个字符。返回值是一个int
类型,用于区分普通字符与EOF
(文件结束符)。 -
feof
:用于检查文件是否已到达末尾,但不能在读取文件时直接判断文件是否结束。通常在文件读取结束后,检查feof
是否为真,来判断是否到达文件末尾。
使用注意事项:
-
每次打开文件后,必须使用
fclose()
关闭文件,防止资源泄漏。 -
fread
和fwrite
操作时不会自动添加字符串结束符\0
,需要手动处理。 -
对于文本文件,使用
fopen
、fread
、fwrite
等标准库函数进行文件操作,适用于大多数应用场景;对于高效、底层的文件操作,可以使用open
、read
、write
等系统调用。 -
调用
fseek
时要确保文件指针在有效范围内。 -
fgetc读取文件时,要根据返回值判断是否读取到文件结束。
-
feof
仅用于检测文件末尾,而不是读取是否成功。建议在fgetc
或fread
读取后检查feof
。