前言
在文件操作函数(一)中,我们已经学会了怎样正确地打开和关闭一个文件,即我们已经学会了一件事的开头和结尾,不要以为已经结束了,这才刚刚开始,真正重要的是打开了文件后,如何操作文件中的数据(输入数据和输出数据)。
对文件数据的读写可以分为顺序读写和随机读写。顺序读写,即挨着顺序对文件中的数据进行输入或输出。
在这片博客中,我们首先介绍文件的顺序读写需要用到的文件操作函数。
字符输入输出函数 - fgetc和fputc
一、fputc函数
int fputc( int c, FILE *stream );
fputc函数的第一个参数是待输出的字符,第二个参数该字符输出的位置,即fputc函数的功能是将一个字符输出到指定的位置。该函数调用完毕会返回用户传入的字符。
例如,我们要将小写字母a~z写入到data.txt文件中。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行输出字符操作
char i = 0;
for (i = 'a'; i <= 'z'; i++)
{
fputc(i, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
二、fgetc函数
int fgetc( FILE *stream );
fgetc函数只有一个参数,即你要读取的文件的文件指针。fgets函数的功能就是从指定位置读取一个字符。该函数调用成功会返回读取到的的字符;若读取文件时发生错误,或是已经读取到文件末尾,则返回EOF。
例如,我们要将文件data.txt文件中的内容全部读取,并打印到屏幕上。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行输入字符操作
int ch = 0;
while ((ch = fgetc(pf))!= EOF)
{
printf("%c", ch);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文本行输入输出函数 - fgets和fputs
一、fputs函数
int fputs( const char *string, FILE *stream );
fputs函数的第一个参数是待输出的字符串,第二个参数该字符串输出的位置,即fputs函数的功能是将一个字符串输出到指定的位置(有没有发现fputs函数的参数设计和fputc函数参数的设计非常类似)。该函数调用成功会返回一个非负值;若输出时发生错误,则返回EOF。
例如,我们要将字符串"hello world!"写入到data.txt文件中。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行输出字符串操作
char arr[] = "hello world!";
fputs(arr, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
二、fgets函数
char *fgets( char *string, int n, FILE *stream );
fgets函数的第三个参数是你要读取的文件的文件指针,第二个参数是你要读取的字符个数(也可以说是字节个数),第一个参数是你所读取到的数据的储存位置。fgets函数的功能就是从指定位置读取指定字符个数的数据储存到指定位置。该函数调用成功会返回用于储存数据的位置的地址,如果读取过程中发生错误,或是读取到了文件末尾,则返回一个空指针(NULL)。
例如,我们要从data.txt文件中提取数据。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行输入字符串操作
char arr[10] = { 0 };
fgets(arr, 6, 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 [, argument ]...);
fprintf函数的第一个参数是数据输出的目的地,后面的参数博友们可能看不太懂,但是我们可以看看库函数printf函数的函数声明:
int printf( const char *format [, argument]... );
//printf函数的声明
我们发现fprintf函数除了第一个参数以外,其它参数都与printf函数的参数一样,虽然我们不知道fprintf函数后面的参数代表的意思,但是我们会用printf函数啊,所以我们使用fprintf函数传参时可以模仿者printf的传参形式。
例如我们要将一个结构体类型的变量信息输出到data.txt文件中去。
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
char name[20];
char sex[5];
int age;
};
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行格式化输出操作
struct S s = { "zhangsan", "nan", 20 };
fprintf(pf, "%s %s %d\n", s.name, s.sex, s.age);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
其实,fprintf函数的功能就是将“区域三”的数据,以“区域二”的格式输出到“区域一”。
二、fscanf函数
int fscanf( FILE *stream, const char *format [, argument ]... );
fscanf函数的第一个参数是读取数据的位置,后面的参数我们也可以类比scanf函数的参数:
int scanf( const char *format [,argument]... );
我们可以看到fscanf函数的参数也是,除了第一个参数以外,其他参数就是scanf函数的参数,于是我们可以试着尝试使用。
例如,我们要将刚才用fprintf函数输出到data.txt文件中的数据读取出来。
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
char name[20];
char sex[5];
int age;
};
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件进行格式化输入操作
struct S tmp = { 0 };
fscanf(pf, "%s %s %d", tmp.name, tmp.sex, &(tmp.age));
printf("%s %s %d\n", tmp.name, tmp.sex, tmp.age);
//将tmp中的内容打印出来,看是否读取成功
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
其实,fscanf函数的功能就是将“区域一”的数据,以“区域二”的格式输入到“区域三”。
二进制输入输出函数 - fread和fwrite
一、fwrite函数
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
fwrite函数的第一个参数是输出数据的位置,第二个参数是要输出数据的元素个数,第三个参数是每个元素的大小,第四个参数是数据输出的目标位置。该函数调用完后,会返回实际写入目标位置的元素个数,当输出时发生错误或是待输出数据元素个数小于要求输出的元素个数时,会返回一个小于count的数。
概括一下,fwrite函数的功能就是将buffer位置的,每个元素大小为size的,count个元素,以二进制的形式输出到stream位置。
例如,我们要将数组arr中的10个元素以二进制的形式输出到data.txt文件中去。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "wb");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件以二进制形式进行输出操作
int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
fwrite(arr, sizeof(int), 10, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
注:此时打开文件的形式应为"wb",即以二进制的形式打开文件,进行输出操作。
二、fread函数
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
fread函数的第一个参数是接收数据的位置,第二个参数是要读取的每个元素的大小,第三个参数是要读取的元素个数,第四个参数是读取数据的位置。函数调用完会返回实际读取的元素个数,若在读取过程中发生错误或是在未读取到指定元素个数时读取到文件末尾,则返回一个小于count的数。
概括一下,fread函数的功能就是从stream位置,以二进制的形式读取count个每个元素大小为size的数据,到buffer位置。
例如,我们要将刚才用fwrite函数输出到data.txt文件的数据读取出来。
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//打开文件
FILE* pf = fopen("data.txt", "rb");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return 1;//文件打开失败,失败返回
}
//对文件以二进制形式进行输入操作
int arr[10] = { 0 };
fread(arr,sizeof(int),10,pf);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}//将arr中的内容打印出来,看是否读取成功
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
注:此时打开文件的形式应为"rb",即以二进制的形式打开文件,进行输入操作。