文章目录
- [一、C 文件读写](#一、C 文件读写)
-
- [1. 打开文件](#1. 打开文件)
- [2. 写入文件](#2. 写入文件)
- [3. 读取文件](#3. 读取文件)
- [4. 关闭文件](#4. 关闭文件)
- [5. 文件读写模式](#5. 文件读写模式)
- [6. 错误处理](#6. 错误处理)
- 二、常见问题
-
- [1. 文件打开失败](#1. 文件打开失败)
- [2. 文件读写错误](#2. 文件读写错误)
- [3. 文件读写位置](#3. 文件读写位置)
- [4. 缓冲区刷新](#4. 缓冲区刷新)
- 三、相关链接
一、C 文件读写
在C语言中,文件读写是通过一系列的标准库函数来完成的,这些函数在stdio.h
头文件中定义。下面是一些常用的文件读写函数及其使用示例。
1. 打开文件
使用fopen
函数打开文件。它返回一个文件指针,该指针在后续的读写操作中会被用到。如果文件打开失败,fopen
会返回NULL
。
c
#include <stdio.h>
int main() {
FILE *file;
file = fopen("example.txt", "w"); // 打开文件以写入,如果文件不存在则创建
if (file == NULL) {
perror("打开文件失败");
return 1;
}
// ... 进行文件写入操作 ...
fclose(file); // 关闭文件
return 0;
}
2. 写入文件
使用fprintf
、fputc
、fputs
等函数将数据写入文件。
fprintf
:格式化写入,类似于printf
。fputc
:写入一个字符。fputs
:写入一个字符串。
c
#include <stdio.h>
int main() {
FILE *file;
file = fopen("example.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
fprintf(file, "Hello, World!\n"); // 写入字符串
fputc('A', file); // 写入字符A
fputs("This is another line.\n", file); // 写入字符串
fclose(file);
return 0;
}
3. 读取文件
使用fscanf
、fgetc
、fgets
等函数从文件中读取数据。
fscanf
:格式化读取,类似于scanf
。fgetc
:读取一个字符。fgets
:读取一行字符串。
c
#include <stdio.h>
#define MAX_LINE 100
int main() {
FILE *file;
char line[MAX_LINE];
file = fopen("example.txt", "r"); // 打开文件以读取
if (file == NULL) {
perror("打开文件失败");
return 1;
}
while (fgets(line, MAX_LINE, file) != NULL) { // 逐行读取文件
printf("%s", line); // 输出读取到的行
}
fclose(file);
return 0;
}
4. 关闭文件
使用fclose
函数关闭文件。在文件读写操作完成后,一定要关闭文件,以释放系统资源。
5. 文件读写模式
fopen
函数的第二个参数指定了文件的打开模式,常用的模式有:
"r"
:只读模式,文件必须存在。"w"
:只写模式,如果文件不存在则创建,如果文件存在则清空文件内容。"a"
:追加模式,如果文件不存在则创建,如果文件存在则在文件末尾追加内容。"r+"
:读写模式,文件必须存在。"w+"
:读写模式,如果文件不存在则创建,如果文件存在则清空文件内容。"a+"
:读写模式,如果文件不存在则创建,如果文件存在则在文件末尾追加内容,并且可以读取文件内容。
还有其他的模式选项,比如二进制模式"b"
(在某些系统上用于区分文本和二进制文件)。例如,"rb"
表示以二进制只读模式打开文件。
6. 错误处理
在文件操作中,应该始终检查fopen
的返回值以确保文件成功打开。如果fopen
返回NULL
,应该使用perror
或strerror
等函数来打印错误信息。同样,在读取或写入文件时也应该检查相应的返回值以确保操作成功。
二、常见问题
在使用C语言进行文件读写时,可能会遇到一些常见问题。以下是一些常见问题及其详细案例代码:
1. 文件打开失败
当尝试打开一个不存在的文件,或者由于其他原因(如权限问题)无法打开文件时,fopen
会返回NULL
。
案例代码:
c
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file;
file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
fprintf(stderr, "打开文件失败: %s\n", strerror(errno));
return 1;
}
// ... 文件操作 ...
fclose(file);
return 0;
}
2. 文件读写错误
在读写文件时,如果发生错误(如磁盘空间不足、文件被截断等),相关的函数(如fread
, fwrite
)会返回一个与预期不符的值。
案例代码(写入错误):
c
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
char buffer[1024] = "这是一些要写入的数据...";
size_t bytes_written;
file = fopen("example.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
bytes_written = fwrite(buffer, sizeof(char), sizeof(buffer), file);
if (bytes_written != sizeof(buffer)) {
fprintf(stderr, "写入文件时发生错误,只写入了%zu字节\n", bytes_written);
}
fclose(file);
return 0;
}
案例代码(读取错误):
c
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
int main() {
FILE *file;
char buffer[BUFFER_SIZE];
size_t bytes_read;
file = fopen("example.txt", "r");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
bytes_read = fread(buffer, sizeof(char), BUFFER_SIZE, file);
if (ferror(file)) {
fprintf(stderr, "读取文件时发生错误\n");
clearerr(file); // 清除错误标志和结束标志
}
// 处理读取到的数据...
fclose(file);
return 0;
}
3. 文件读写位置
默认情况下,文件读写操作是从文件的开始位置进行的。但是,可以使用fseek
函数来移动文件读写位置。
案例代码:
c
#include <stdio.h>
int main() {
FILE *file;
char buffer[10];
file = fopen("example.txt", "r+"); // 以读写模式打开文件
if (file == NULL) {
perror("打开文件失败");
return 1;
}
// 假设文件内容是 "Hello, World!"
// 移动到文件的第7个字节处('W'的位置)
if (fseek(file, 6, SEEK_SET) != 0) { // SEEK_SET表示从文件开始位置计算偏移量
perror("fseek失败");
fclose(file);
return 1;
}
// 读取接下来的3个字节
if (fread(buffer, sizeof(char), 3, file) != 3) {
perror("fread失败");
} else {
printf("读取到的内容是: %s\n", buffer); // 输出 "Wor"
}
fclose(file);
return 0;
}
4. 缓冲区刷新
在C语言中,当使用printf
、fprintf
等函数向文件或标准输出(如控制台)写入数据时,这些数据首先会被写入到一个内部缓冲区中,而不是直接写入到文件或输出设备。这种缓冲机制是为了提高I/O效率,因为将数据写入缓冲区通常比直接写入到设备要快得多。然而,在某些情况下,你可能希望立即将数据从缓冲区刷新(flush)到目标设备。
在文件I/O中,你可以使用fflush
函数来刷新文件缓冲区。fflush
函数接受一个文件指针作为参数,并将该指针指向的文件的所有未写入的数据立即写入到文件中。如果参数是NULL
,则fflush
会刷新所有打开的文件流。
下面是一个使用fflush
刷新文件缓冲区的示例代码:
c
#include <stdio.h>
int main() {
FILE *file;
// 打开文件以写入
file = fopen("example.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
// 写入一些数据到缓冲区
fprintf(file, "Hello, World!\n");
// 刷新缓冲区,将数据立即写入到文件
if (fflush(file) != 0) {
perror("刷新文件缓冲区失败");
fclose(file);
return 1;
}
// 写入更多的数据到缓冲区
fprintf(file, "This is another line.\n");
// 关闭文件,这也会隐式地刷新缓冲区
fclose(file);
return 0;
}
在上面的示例中,我们首先使用fprintf
函数将一些数据写入到文件缓冲区中。然后,我们调用fflush(file)
来立即将这些数据从缓冲区刷新到文件中。之后,我们又写入了更多的数据到缓冲区,但这次我们没有显式地调用fflush
,而是在最后关闭文件时,缓冲区会被隐式地刷新。
需要注意的是,关闭文件(使用fclose
函数)也会刷新该文件的缓冲区。因此,如果你确信在文件操作完成后会关闭文件,那么通常不需要显式地调用fflush
。然而,在某些情况下,你可能希望在关闭文件之前立即看到写入的数据,这时就可以使用fflush
函数来刷新缓冲区。