今天我们来一起学习文件读写的两个非常重要的函数fread和fwrite。先来看看它们的定义:
size_t fread (void *data, size_t size, size_t count, FILE *stream);
size_t fwrite (const void *data, size_t size, size_t count, FILE *stream);
我们可以看到这两个函数的定义基本上是一样的,只不过一个是读,而另一个是写。
在这里我们来看看关于第二个参数和第三个参数的作用。例如我们希望从文件中读取10个int型变量可以这样书写代码:
int buff[10];
fread(buff, sizeof(int), 10, fp);
其中我们指定了单个读取块的大小sizeof(int)并指定了读取的个数10,所以在这段代码执行后会总共读取4*10=40个字节到内存数组中(注意:此时函数的返回值为10)。其实我们还可以这样来编写代码:
int buff[10];
fread(buff, 1, 40, fp);
这样一次读取1个字节,总共读取40个字节,这跟上面的代码没有什么本质区别(注意:此时函数的返回值为40)。但是从功能上讲第一段程序更加容易理解。我们来看看使用这两个函数来保存和读取结构体的例子:
#include <stdio.h>
#include <string.h>
struct student
{
int id;
int age;
char name[20];
} stu[3];
int main(int argc, char *argv[])
{
stu[0].id = 1;
stu[0].age = 26;
strcpy(stu[0].name, "lidq");
stu[1].id = 2;
stu[1].age = 27;
strcpy(stu[1].name, "baiy");
stu[2].id = 3;
stu[2].age = 23;
strcpy(stu[2].name, "liux");
FILE *fp = fopen("/data/temp/stu", "w");
size_t cnt = fwrite(stu, sizeof(struct student), 3, fp);
printf("write cnt = %d.\n", cnt);
fclose(fp);
fp = fopen("/data/temp/stu", "r");
cnt = fread(stu, sizeof(struct student), 3, fp);
printf("read cnt = %d.\n", cnt);
fclose(fp);
return 0;
}
这样我们就把在程序中以结构体方式存在的变量保存到了文件中,并再用结构体的方式将文件内容读取到内存变量中。注意我们在上面介绍的内容都是将内存中的变量直接保存到文件中去,没有做任何的字符转换,所以文件中的内容与内存中的变量内容一致,都是二进制文件,而不是字符型文件(文本文件)。
接下来我们来编程一个存储文本文件的例子:
#include <stdio.h>
#include <string.h>
struct student
{
int id;
int age;
char name[20];
} stu[3];
int main(int argc, char *argv[])
{
stu[0].id = 1;
stu[0].age = 26;
strcpy(stu[0].name, "lidq");
stu[1].id = 2;
stu[1].age = 27;
strcpy(stu[1].name, "baiy");
stu[2].id = 3;
stu[2].age = 23;
strcpy(stu[2].name, "liux");
char buff[100];
FILE *fp = fopen("/data/temp/stu", "w");
for (int i = 0; i < 3; i++)
{
int len = snprintf(buff, 100, "%d, %d, %s\n", stu[i].id, stu[i].age, stu[i].name);
fwrite(buff, 1, len, fp);
}
fclose(fp);
return 0;
}
这里我们使用了一个snprintf函数可以将指定的变量打印到字符数组中。我们打开/data/temp/stu文件之后可以看到其内容如下:
1, 26, lidq
2, 27, baiy
3, 23, liux
Copyright © 2015-2023 问渠网 辽ICP备15013245号