i n t int int c h a r a c t e r character character:要写入的字符,字符的本质就是 A S C I I ASCII ASCII 码值,因此这里参数类型为 i n t int int 没有问题
F I L E FILE FILE * s t r e a m stream stream :指向要写入文件的文件指针
返回类型:返回类型是 int:当写入乐成,返回写入的值,当写入失败,返回EOF(-1)
函数使用:
#include<stdio.h>
int main()
{
FILE* pf = NULL;
//打开文件
pf = fopen("test.txt", "w");
//文件操作
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
//写文件
fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
//写入26个字母
char ch = 0;
for (ch = 'a'; ch <= 'z'; ch++)
{
fputc(ch, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
复制代码
这样,字符就写好了。
当写入字符时,还有一些细节需要注意:当一个文件打开时,最开始其实是有一个光标指向第一个位置,每当用 f p u t c fputc fputc 函数写入一个字符,光标则退却一格。光标是用来维护此时如今我们这个文件写到哪的,而且是按照一定的次序往后走的,因此叫做次序读写
5.3、 f g e t c fgetc fgetc 函数
函数功能:从流(文件)中获取一个字符
返回值:返回类型为 i n t int int 。假如乐成,就会将读到的字符返回,假如读取失败大概遇到文件末尾返回EOF(-1)
为什么返回类型是 int 呢?正是因为它会返回两种类型的值:字符的 A S C I I ASCII ASCII码 值和 EOF;假如返回类型为 char,则 EOF 无法返回
函数使用:
#include<stdio.h>
int main()
{
FILE* pf = NULL;
//打开文件
pf = fopen("test.txt", "r");
//文件操作
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
//读文件
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}
printf("\n");
//关闭文件
fclose(pf);
pf = NULL;
}
复制代码
运行结果:
而同样,以只读的方式打开文件,刚开始光标是在第一个位置,即指向 a a a,每读一个字符,光标向退却一位。
5.4、 f p u t s fputs fputs 函数
函数功能:将 str 字符串写入文件流中,直至遇到 ‘\0’ 制止(‘\0’不会被写入)
注:多次调用该函数,并不会实现自动换行,要想换行应自动输入‘\n’
函数使用:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = NULL;
pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
//写文件
fputs("hello", pf);
fputs("world\n", pf);
fputs("hello csdn\n", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
复制代码
运行结果:
我们可以看到,加了换行符后,文件的光标是直接落到下一行的。
5.5、 f g e t s fgets fgets 函数
函数功能:从流中最多读取 num 个字符,并放在 str 所指向的空间中
函数读 n u m num num 个字符,但是最多只能读取 n u m num num - 1个,因为最后一个位置函数会自己加上 ‘\0’
该函数不会换行读取。当 n u m num num 大于字符数时,遇到换行符 ‘\n’,将 ‘\n’ 读取后,不再往下读取,自己加上 ‘\0’ 后制止。
当函数读取乐成,返回的是目的空间的地点;读取失败则返回空指针(NULL)
函数使用:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = NULL;
pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
//读文件
char arr1[10] = "xxxxxxxxx";
fgets(arr1, 8, pf);
char arr2[10] = "xxxxxxxxx";
fgets(arr2, 8, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
复制代码
运行结果:
5.6、 f p r i n t f fprintf fprintf 函数
该函数的功能是将数据以格式化的形式写入流中(以文本的形式)
其实, f p r i n t f fprintf fprintf 函数和 p r i n t f printf printf 函数是非常相像的,让我们来对比一下
他们的区别仅仅是第一个参数的有无而已,其他都是千篇一律的,所以你会用 p r i n t f printf printf你就会用 f p r i n t f fprintf fprintf
多的一个参数是什么呢?是文件流,你需要将数据输出到的那个文件流
#include<stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "张三", 20, 75.5f };
//打开文件
FILE* pf = NULL;
pf = fopen("test.txt", "w");
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
//写文件
fprintf(pf, "%s %d %f", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
复制代码
运行结果:
5.7、 f s c a n f fscanf fscanf 函数
该函数的功能是从文件流中读取格式化的数据。
不难发现, f s a n f fsanf fsanf 与 s c a n f scanf scanf 函数很像,我们来对比一下
同 f p r i n t f fprintf fprintf 一样, f s c a n f fscanf fscanf 与 s c a n f scanf scanf 只是相差一个参数而已,你会用 s c a n f scanf scanf 自然也就会用 f s c a n f fscanf fscanf 函数,第一个参数即是你所要读取的文件流。
注意看,上述代码用了 f p r i n t f fprintf fprintf 来将数据打印在屏幕上
还记得最开始的表格中, f p r i n t f fprintf fprintf 最后一列写的是所有输出流吗?这所有输出流就包括了文件流和标准输出流,既然 f p r i n t f fprintf fprintf 可以输出到文件中,那么自然也就可以输出到屏幕中,完成 p r i n t f printf printf 一样的功能。
而同理,前面讲的 f p u t c fputc fputc、 f g e t s fgets fgets、 f s c a n f fscanf fscanf 等函数也可以从标准输入(输出)流中获取(输出)数据。
5.8、 p r i n t f / f p r i n t f / s p r i n t f printf/fprintf/sprintf printf/fprintf/sprintf 函数对比
通过我们前面的学习,我们已经知道了 p r i n t f printf printf 和 f p r i n t f fprintf fprintf 函数的作用:
p r i n t f printf printf:把数据以格式化的形式打印在标准输出流上
f p r i n t f fprintf fprintf : 把数据以格式化的形式打印在 指定的输出流 上
那么 s p r i n t f sprintf sprintf 函数又是作什么的呢?我们一起来看看
该函数的作用是:将数据以格式化的形式写到字符串上。其实就是把格式化的数据转换成字符串
#include<stdio.h>
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "张三", 20, 75.5f };
char buf[50] = { 0 };
sprintf(buf, "%s %d %f", s.name, s.age, s.score);
printf("%s\n", buf);
return 0;
}
复制代码
运行结果:
该代码完全是以 %s 的形式打印的,说明数据已经完全转换成字符串了。
5.9、 s c a n f / f s c a n f / s s c a n f scanf/fscanf/sscanf scanf/fscanf/sscanf 函数对比
同样,通过我们前面的学习,我们已经知道了 s c a n f scanf scanf 和 f s c a n f fscanf fscanf 函数的作用:
s c a n f scanf scanf:从 标准输入流 中读取格式化的数据
f s c a n f fscanf fscanf:从 指定输入流 中读取格式化的数据
那 s s c a n f sscanf sscanf 的功能又是什么呢?学习了 s p r i n t f sprintf sprintf ,我们猜测,其应该是从字符串中读取格式化数据,是不是呢?我们一起来看看
l o n g long long i n t int int o f f s e t offset offset:相对于起始位置的偏移量,可正可负
i n t int int o r i g i n origin origin:起始位置
起始位置选择:
常量所指位置SEEK_SET文件的起始位置SEEK_CUR当前光标位置SEEK_END文件末端
这个函数有什么用呢?好比文件中有 a b c d e f g abcdefg abcdefg 的数据,当前光标指向 a a a,而我想直接读 e e e,这时就可以用该函数移动光标啦。
例子:
#inclu<stdio.h>
int main()
{
FILE* pf = NULL;
pf = fopen("test.txt", "r");
if (NULL == pf)
{
perror("fopen fail");
return 1;
}
char ch = 0;
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, 3, SEEK_CUR);
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
复制代码
运行结果:
6.2、 f t e l l ftell ftell 函数
f t e l l ftell ftell 函数会返回文件指针(光标) 相对于文件起始位置的 偏移量
这里,我们想:假如我们让光标读到文件末尾,在返回偏移量,是不是就能知道文件的长度呢?答案是肯定的。
例子:
#includ<stdio.h>
int main()
{
FILE* pf;
long size;
pf = fopen("test.txt", "rb");
if (NULL == pf)
perror("Error opening file");
fseek(pf, 0, SEEK_END); // non-portable
size = ftell(pf);
fclose(pf);
printf("Size of test.txt: %ld bytes.\n", size);
return 0;
}
复制代码
6.3、 r e w i n d rewind rewind 函数
r e w i n d rewind rewind 函数可以让文件指针回到起始位置
走的太远,别忘了回头路 例子:
#include<stdio.h>
int main()
{
int n;
FILE* pf;
char buffer[27];
pf = fopen("test.txt", "w+");
for (n = 'A'; n <= 'Z'; n++)
{
fputc(n, pf);
}
rewind(pf);
fread(buffer, 1, 26, pf);
fclose(pf);
buffer[26] = '\0';
printf(buffer);
return 0;
}
复制代码
七、文件读取结束的判断
7.1、 被错误使用的 f e o f feof feof
很多人都以为 f e o f feof feof函数是用来直接判断文件读取是否结束。其实这是大错特错的
f e o f feof feof 的作用是:当文件读取结束时,判断读取结束的原因是否是因为:遇到文件末尾结束。
如今假设文件读取结束了,但是是什么原因读取结束的呢?
有可能遇到文件末尾
读取的时候发生了错误
f e o f feof feof 函数是判断是否是因为遇到文件末尾而结束的。
而还有个函数叫 f e r r o r ferror ferror 是用来判断是否是因为遇到错误而读取结束的
其实在我们打开一个流时,会有两个标记值
是否遇到文件末尾
是否发生错误
当读文件的过程中确实是遇到文件末尾了,就会将第一个值标记;遇到错误就会将第二个值标记。
f e o f feof feof是用来检测第一个标记的; f e r r o r ferror ferror是用来检测第二个标记的
f e o f feof feof 函数:当文件确实是因为读取到文件末尾而结束时,返回一个非零值,反之返回 0