前言,在上篇博客介绍了如何正确的打开一个文件和关闭一个文件,今天我们来学习如何在文件中输出和输入数据。
对文件数据的读写可以分为顺序读写和随机读写。顺序读写,即挨着顺序对文件中的数据进行输入或输出。
在这片博客中,我们首先介绍文件的顺序读写需要用到的文件操作函数。
我们今天这篇博客主要介绍这几个文件操作函数。
字符输入输出函数 - fgetc和fputc
fputc函数
int fputc ( int character, FILE * stream );
fputc函数的第一个参数是待输出的字符,第二个参数该字符输出的位置,即fputc函数的功能是将一个字符输出到指定的位置。该函数调用完毕会返回用户传入的字符
比如我们要输出26个字符到test.txt的文件中去。
int main()
{
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("open");
return 1;
}
//对文件的一系列操作
char i = 'a';
for (i = 'a'; i <= 'z'; i++)
{
fputc(i, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgetc文件输入函数
int fgetc ( FILE * stream );
fgetc函数只有一个参数,就是从你传入的文件指针开始读取一个字符。调用成功会返回所读取到的字符,而读取错误就会返回EOF。
我们将刚刚打印的26个字符全部读出来并打印到屏幕上。
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c", ch);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文本行输入函数-fgets和fputs(字符串输入和输出函数)
fputs
char * fgets ( char * str, int num, FILE * stream );
str表示要写的字符串,stream表示要输出的位置。即fputs函数的功能是将一个字符串输出到指定的位置(有没有发现fputs函数的参数设计和fputc函数参数的设计非常类似)。该函数调用成功会返回一个非负值;若输出时发生错误,则返回EOF。
我们来实现一个将welcome to china写进文件中试试
int main()
{
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
fputs("welcome to china", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgets
har * fgets ( char * str, int num, FILE * stream );
str表示将读取到的字符串放到所指的字符指针中去,num表示读取的数量,stream表示读取的位置。
第一个参数是你所读取到的数据的储存位置。fgets函数的功能就是从指定位置读取指定字符个数的数据储存到指定位置。该函数调用成功会返回用于储存数据的位置的地址,如果读取过程中发生错误,或是读取到了文件末尾,则返回一个空指针(NULL)
我们将刚刚中文本文件中写入的字符串读出三个试试。
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
char arr[20] = { 0 };
fgets(arr,3,pf);
printf("%s\n",arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgets函数读取字符的过程中会出现两种情况:
在fgets函数读取到指定字符数之前,若读取到换行符(’\n’),则停止读取,读取带回的字符包含换行符。
直到fgets函数读取到第n-1个字符时都没有遇到换行符(’\n’),则返回读取到的n-1个字符,并在末尾加上一个空字符一同返回(共n个字符)
格式化输入输出函数-fscanf和fprintf
fprintf
int fprintf ( FILE * stream, const char * format, ... );
第一个是输出数据的目的地,后面的用法跟我们平时使用的printf用法一样,就是在前面多一个指针而已
例如我们要将一个结构体的类型的指针输出到文本文件中,我们可以这样子做
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s[2] = { {"wangchengdong",22,98.5},{"liumeili",24,96.5} };
FILE* pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen");
return 1;
}
for (int i = 0; i < 2; i++)
{
//对文件的一系列操作
fprintf(pf, "%s %d %f\n", s[i].name, s[i].age, s[i].score);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
其实,fprintf函数的功能就是将“区域三”的数据,以“区域二”的格式输出到“区域一”。
fscanf函数
int fscanf ( FILE * stream, const char * format, ... );
这俩个是非常相似的,我们可以将刚刚fprintf函数输出到文本文件中的结构体读取出来。
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s[2] = {0};
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
fscanf(pf,"%s %d %f %s %d %f\n",s[0].name, &(s[0].age), &(s[0].score),s[1].name,&(s[1].age),&(s[1].score));
int i = 0;
for (i = 0; i < 2; i++)
{
printf("%s %d %.1f\n",s[i].name,s[i].age,s[i].score);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
其实,fscanf函数的功能就是将“区域一”的数据,以“区域二”的格式输入到“区域三”
fwrite和fread二进制文件的读写
fwrite
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
fwrite函数的第一个参数是输出数据的位置,第二个参数是要输出数据的元素个数,第三个参数是每个元素的大小,第四个参数是数据输出的目标位置。该函数调用完后,会返回实际写入目标位置的元素个数,当输出时发生错误或是待输出数据元素个数小于要求输出的元素个数时,会返回一个小于count的数。
比如我们要把刚刚的结构体信息写进二进制文件中去。
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s[2] = { {"wangchengdong",22,98.5},{"liumeili",24,96.5} };
FILE* pf = fopen("test.txt", "wb");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
fwrite(s,2,sizeof(struct S),pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
此时打开文件的方式是wb的形式,是二进制的形式
fread
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
fread函数的第一个参数是接收数据的位置,第二个参数是要读取的每个元素的大小,第三个参数是要读取的元素个数,第四个参数是读取数据的位置。函数调用完会返回实际读取的元素个数,若在读取过程中发生错误或是在未读取到指定元素个数时读取到文件末尾,则返回一个小于count的数。
我们将刚刚的二进制文件读出来并打印在屏幕上
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s[2] = {0};
FILE* pf = fopen("test.txt", "rb");
if (NULL == pf)
{
perror("fopen");
return 1;
}
//对文件的一系列操作
struct S tmp[5] = { 0 };
fread(tmp,5,sizeof(struct S),pf);
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%s %d %.1f\n", tmp[i].name, tmp[i].age, tmp[i].score);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}