一、打开文件fopen
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
功能:创建或者打开一个文件
参数:
path:文件名,如果只写文件名,默认就是当前路径,也可以添加路径
mode:文件权限
r 只读,如果文件不存在则报错
r+ 读写,如果文件不存在则报错
w 只写,如果文件不存在则创建,如果文件存在则清空
w+ 读写,如果文件不存在则创建,如果文件存在则清空
a 只写,如果文件不存在则创建,如果文件存在则追加
a+ 读写,如果文件不存在则创建,如果文件存在则追加
返回值:
成功:文件指针
失败:NULL
案例
#include <stdio.h>
int main(int argc, char *argv[])
{
//使用fopen函数打开或者创建文件,返回文件指针
FILE *fp;
//以只写的方式打开文件,如果文件不存在则创建,如果文件存在则追加
fp = fopen("C:/Users/lzx/Desktop/file.txt", "a");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
return 0;
}
这段代码演示了如何使用
fopen
函数以追加模式("a"
)打开或创建一个文件。如果文件"C:/Users/lzx/Desktop/file.txt"
不存在,它将被创建;如果文件存在,新的内容将被追加到文件末尾。在打开文件后,程序会检查是否成功打开文件,如果失败则会输出错误信息并返回-1
。如果打开文件成功,程序将正常返回0
。
二、关闭文件fclose
#include <stdio.h>
int fclose(FILE *stream);
功能:关闭一个文件指针,无法再对当前文件进行操作。
参数:
stream:指定的文件指针,即 `fopen` 函数的返回值。
返回值:
成功:返回 0。
失败:返回 EOF(End Of File),通常定义为 -1。
注意:
- 一个文件只能关闭一次,不能多次关闭。
- 关闭文件之后,就不能再使用该文件指针对文件进行读写等操作了。
我们首先使用
fopen
函数以追加模式("a"
)打开或创建文件"C:/Users/lzx/Desktop/file.txt"
。然后,我们检查文件是否成功打开:如果fp
为NULL
,则表示打开文件失败,程序会输出错误信息并返回-1
;如果文件打开成功,我们将使用fclose
函数关闭文件,释放与文件相关的系统资源。最后,程序正常返回0
三、一次读写一个字符
3.1 fgetc
#include <stdio.h>
int fgetc(FILE *stream);
功能:从文件指针标识的文件中读取一个字符。
参数:
stream: 指定的文件指针。
返回值:
成功:读取的字符。
失败:EOF(End Of File),通常表示文件末尾或读取错误。
注意:如果文件读取完毕,`fgetc` 函数也会返回 EOF。
实现的案例
file.txt中的内容
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "r");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 使用fgetc从文件中读取一个字符
// int c = fgetc(fp);
// printf("c = [%c] - %d\n", c, c);
// c = fgetc(fp);
// printf("c = [%c] - %d\n", c, c);
// 执行结果:文件的每一行结束的位置都有一个标识,是一个换行符,称之为行结束符
// fgetc可以读取到行结束符
int c;
while((c = fgetc(fp)) != EOF)
{
printf("c = [%c] - %d\n", c, c);
}
// 关闭文件
fclose(fp);
return 0;
}
3.2 fputc
#include <stdio.h>
int fputc(int c, FILE *stream);
功能:向文件指针标识的文件中写入一个字符。
参数:
c: 要写入的字符。
stream: 指定的文件指针。
返回值:
成功:返回要写入的字符 `c`。
失败:返回 `EOF`(End Of File),通常表示写入错误。
案例
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "w");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 通过fputc函数向文件写入一个字符
fputc('w', fp);
fputc('h', fp);
fputc('a', fp);
fputc('t', fp);
fputc('\n', fp); // 换行符
fputc('o', fp);
// 关闭文件
fclose(fp);
return 0;
}
执行结果
四、一次读写一个字符串
4.1 fgets
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
功能:从文件中读取内容。
参数:
s: 保存读取到的内容的字符数组。
size: 每次读取的最大字符数(包括结束符 `\0`)。
stream: 文件指针,指向要读取的文件。
返回值:
成功:返回指向读取数据的首地址的指针,即 `s`。
失败:返回 `NULL`,表示读取错误或文件结束。
注意:
- `fgets` 函数从 `stream` 所指的文件中读取字符,直到遇到换行符(`\n`)、文件末尾或读取了 `size - 1` 个字符为止。
- 在读取的内容后面会自动添加一个空字符(`\0`)作为字符串的结尾。
- 如果在读取过程中遇到文件末尾,或者读取了 `size - 1` 个字符后仍未遇到换行符或文件末尾,则返回 `NULL`。
- 如果文件内容读取完毕,`fgets` 函数也会返回 `NULL`。
案例
文件中的内容
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "r");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 使用fgets读取文件内容
// fgets每次读取时最多读取文件一行内容,只要遇到行结束符就立即返回
// 如果想要读取的字节数小于一行内容,则只会读取第二个参数-1个字节,最后位置补\0
char buf[32] = "";
// fgets(buf, 8, fp); // 如果只想读取8个字符,可以解注释这行代码并注释下一行
fgets(buf, 32, fp); // 读取一行内容到buf中,最多读取31个字符(32-1=31)
printf("buf = %s\n", buf); // 输出读取到的内容
// 关闭文件
fclose(fp);
return 0;
}
这段代码演示了如何使用
fgets
函数从文件"C:/Users/lzx/Desktop/file.txt"
中读取一行内容。首先,程序以只读模式("r"
)打开文件。然后,使用fgets
函数将文件中的一行内容读取到字符数组buf
中,最多读取32 - 1 = 31
个字符,并在最后添加一个空字符(\0
)作为字符串的结尾。最后,使用printf
函数将读取到的内容输出到控制台。如果文件打开失败,程序会输出错误信息并返回-1
。在读取和输出内容后,使用fclose
函数关闭文件。
执行结果
4.2 fputs
#include <stdio.h>
int fputs(const char *s, FILE *stream);
功能:向文件写入数据。
参数:
s: 要写入的内容的字符串指针。
stream: 文件指针,指向要写入的文件。
返回值:
成功:返回非负值,表示写入文件内容的字节数。
失败:返回 `EOF`(End Of File),表示写入错误。
案例
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "w");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 通过fputs函数向文件写入数据
fputs("66666666666666\n", fp);
fputs("nihao", fp);
// 关闭文件
fclose(fp);
return 0;
}
这段代码使用
fputs
函数向文件"C:/Users/lzx/Desktop/file.txt"
写入两段字符串。首先,程序以写入模式("w"
)打开文件,如果文件不存在则创建,如果存在则覆盖原有内容。然后,使用fputs
函数将字符串 "66666666666666\n" 和 "nihao" 写入文件中。其中,\n
表示换行符,用于在文件中创建新的一行。最后,使用fclose
函数关闭文件,完成写入操作。如果文件打开失败,程序会输出错误信息并返回-1
。
执行结果
五、读文件fread
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件中读取数据。
参数:
ptr: 保存读取的数据的指针。
size: 每次读取的字节数。
nmemb: 一共读取的对象(元素)数量。
stream: 文件指针,指向要读取的文件。
返回值:
成功:返回实际读取的对象(元素)数量,即成功读取的块数。
失败:返回 0,表示读取错误或文件结束。
注意:
- `fread` 函数从文件 `stream` 中读取数据,并将它们存储在由 `ptr` 指向的内存块中。
- 读取的总字节数是 `size` 和 `nmemb` 的乘积。
- 如果在读取过程中遇到文件末尾,或者读取了部分数据后发生错误,`fread` 函数将返回已成功读取的对象数量。
- 如果文件内容读取完毕,或者读取过程中发生错误,`fread` 函数将返回 0。
举例1
int num;
num = fread(str, 100, 3, fp);
返回值num,从fp所代表的文件中读取内容存放到str指向的内存中,读取的字节数为每块100个字节,共3块。如果读到300个字节,返回值num为3。
如果读到了大于等于200个字节小于300个字节,返回值为2。
读到的字节数大于等于100个字节小于200个字节,返回1。
不到100个字节,返回0。
文件中的内容
举例2
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "r");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 使用fread函数读取文件内容
int num;
char buf[128] = "";
num = fread(buf, 5, 4, fp); // 每次读取5个字节,共读取4次
printf("buf = %s\n", buf);
printf("num = %d\n", num);
// 关闭文件
fclose(fp);
return 0;
}
执行结果
六、写文件fwrite
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:向文件中写入数据。
参数:
ptr: 要写入的数据的指针。
size: 一次写入的字节数。
nmemb: 一共写入的对象(元素)数量。
stream: 文件指针,指向要写入的文件。
返回值:
成功:返回实际写入的对象(元素)数量,即成功写入的块数。
失败:返回 0,表示写入错误。
举例
#include <stdio.h>
typedef struct{
int a;
int b;
char c;
}MSG;
int main(int argc, char *argv[])
{
FILE *fp;
fp = fopen("C:/Users/lzx/Desktop/file.txt", "w+");
if(fp == NULL)
{
printf("fail to fopen\n");
return -1;
}
// 使用fwrite向文件写入一个结构体
MSG msg[4] = {
{1, 2, 'a'},
{3, 4, 'b'},
{5, 6, 'c'},
{7, 8, 'd'}
};
fwrite(msg, sizeof(MSG), 4, fp);
// 将文件的偏移量设置为文件的起始位置
rewind(fp);
MSG rcv[4];
fread(rcv, sizeof(MSG), 4, fp);
int i;
for(i = 0; i < 4; i++)
{
printf("%d - %d - %c\n", rcv[i].a, rcv[i].b, rcv[i].c);
}
// 关闭文件
fclose(fp);
return 0;
}
执行结果
七、格式化读写文件函数
fprintf 函数
int fprintf(FILE *stream, const char *format, ...);
参数
stream
:指向文件的指针,表示要写入数据的文件。format
:格式化字符串,用于指定输出数据的格式。...
:可变参数列表,包含要写入文件的数据。
功能
fprintf
函数根据 format
字符串中的格式说明符,将数据转换为指定格式,并将结果写入到 stream
所指向的文件中。格式说明符与 printf
函数中的格式说明符相同,例如 %d
表示整数,%f
表示浮点数等。
fprintf 和printf函数类似: printf是将数据输出到屏幕上(标准输出),fprintf函数是将数据输出到文件指针所指定的文件中。
返回值
fprintf
函数返回成功写入的字符数量,如果发生错误则返回负值。
fscan函数
int fscanf(FILE *stream, const char *format, ...);
参数
stream
:指向文件的指针,表示要读取数据的文件。format
:格式化字符串,用于指定读取数据的格式。...
:可变参数列表,包含指向存储读取数据的变量的指针。
功能
fscanf
函数根据 format
字符串中的格式说明符,从 stream
所指向的文件中读取数据,并将它们存储在相应的变量中。格式说明符与 scanf
函数中的格式说明符相同,例如 %d
表示整数,%f
表示浮点数等。
fscanf和scanf 函数类似: scanf是从键盘(标准输入)获取输入, fscanf是从文件指针所标示的文件中获取输入。
返回值
fscanf
函数返回成功读取的数据项数量,如果发生错误或到达文件末尾则返回 EOF
(通常为 -1
)。
举例
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
char ch1 = 'a', ch2;
int num1 = 50, num2;
char string1[20] = "hello", string2[20];
float score1 = 85.5, score2;
if((fp = fopen("C:/Users/lzx/Desktop/file.txt","w+"))==NULL)
{
printf("fail to fopen\n");
return -1;
}
// 使用fprintf向文件写入字符串
fprintf(fp,"%c %d %s %f\n", ch1, num1, string1, score1);
// 将文件指针重置到文件开头
rewind(fp);
// 使用fscanf获取文件内容
fscanf(fp,"%c %d %s %f\n", &ch2, &num2, &string2, &score2);
printf("%c %d %s %f\n", ch2, num2, string2, score2);
// 关闭文件
fclose(fp);
return 0;
}
执行结果
实现
八、随机读写
前面介绍的对文件的读写方式都是顺序读写,即读写文件只能从头开始,顺序读写各个 数据;
但在实际问题中常要求只读写文件中某一指定的部分,例如:读取文件第200--300个字节
为了解决这个问题可以移动文件内部的位置指针到需要读写的位置,再进行读写,这种读写称为随机读写实现随机读写的关键是要按要求移动位置指针,这称为文件的定位.
8.1 rewind
#include <stdio.h>
void rewind(FILE *stream);
功能:
将文件位置定位到起始位置
参数:
stream:文件指针
返回值:
无
8.2 ftell
#include <stdio.h>
long ftell(FILE *stream);
功能:获取当前文件的偏移量。
参数:
stream: 文件指针,指向要获取偏移量的文件。
返回值:
成功:返回当前文件的偏移量,即文件指针相对于文件开头的位置(以字节为单位)。
失败:返回 -1L,表示出现错误。
8.3 fseek
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:设置文件位置指针的偏移量。
参数:
stream: 文件指针,指向要设置偏移量的文件。
offset: 偏移量,可正可负,表示从 `whence` 位置开始移动的字节数。
whence: 相对位置,指定偏移量的基准位置,可以是以下三个常量之一:
- SEEK_SET: 表示从文件起始位置开始计算偏移量。
- SEEK_CUR: 表示从文件当前位置开始计算偏移量。
- SEEK_END: 表示从文件末尾位置开始计算偏移量(即最后一个字符后面一个位置)。
返回值:
成功:返回 0。
失败:返回 -1,表示设置偏移量时发生错误。
注意:
- `rewind(fp)` 等价于 `fseek(fp, 0, SEEK_SET);`,即把文件指针重置到文件开头。
举例
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp;
if((fp = fopen("C:/Users/lzx/Desktop/file.txt","w+"))==NULL)
{
printf("fail to fopen\n");
return -1;
}
fputs("123456789\n", fp);
fputs("abcdefghijklmn", fp);
// 获取当前文件指针的读写位置
printf("offset = %ld\n", ftell(fp));
// 将当前文件的读写位置设置为倒数第五个位置
fseek(fp, -5, SEEK_END);
char buf[32] = "";
while(fgets(buf, 32, fp) != NULL)
{
printf("[%s]\n", buf);
}
// 关闭文件
fclose(fp);
return 0;
}
文件中的内容
实现