文件操作在初级C语言中是一个概念多且繁琐的章节。本篇文章采用先总后分的写法,适合于学C语言的程序猿阅读,相信这里面的内容在你看过的文件操作专题都大体出现过。觉得这篇文章总结的较为详细的话别忘了收藏与关注哦(鄙人觉得扩展的还挺全面的),我是一枚小比特,希望在接下来的沉潜岁月里陪你一起努力勇攀高峰!
目录
文件类型、文件名。文件系统
主要函数总结
主要文件打开方式
fopen()与flcose()
fgetc()与fputc()
fgets()与fputs()
fread()与fwrite()
关于被错误使用的feof()
尾声
文件类型、文件名。文件系统
C语言文件有两种类型:二进制文件(demo.bin)和文本文件(demo.txt)。
文件名包括三部分:文件路径+文件名主干+文件后缀 e.g:D:\shilv\test.txt
C语言文件系统也有两种类型:缓冲型(利用文件指针标识文件)非缓冲型(没有文件指针,使用称为文件号的整数来标识文件)。本文章主要介绍的是缓冲型文件系统。
缓冲型文件系统中,关键性概念是“文件类型指针”,简称“文件指针”。
文件指针pf(有些教材上是fp,和本文章的pf的唯一区别是字母不同而已)是指向FILE结构类型的指针变量,其定义为
FILE* pf
主要函数总结
函数 | 函数原型 | 大致用法 |
fopen() | FILE *fopen( const char *filename, const char *mode ) |
|
fclose() | int fclose( FILE *stream ) |
|
fgetc() | int fgetc( FILE *stream ) |
|
fputc() | int fputc( int c, FILE *stream ) |
|
fgets() | char *fgets( char *string, int n, FILE *stream ) |
|
fputs() | int fputs( const char *string, FILE *stream ) |
|
feof() | int feof( FILE *stream ) |
|
fscanf() | int fscanf( FILE *stream, const char *format [, argument ]... ) |
|
fprintf() | int fprintf( FILE *stream, const char *format [, argument ]...) |
|
fread() | size_t fread( void *buffer, size_t size, size_t count, FILE *stream ) |
|
fwrite() | size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ) |
|
strerror() | char *strerror( int errnum ) |
|
perror() | void perror( const char *string ) |
|
sscanf() | int sscanf( const char *buffer, const char *format [, argument ] ... ) | |
sprintf() | int sprintf( char *buffer, const char *format [, argument] ... ) | |
fseek() | int fseek( FILE *stream, long offset, int origin ) |
|
ftell() | long ftell( FILE *stream ) |
|
rewind() | void rewind( FILE *stream ) | |
fflush() | int fflush( FILE *stream ) | |
如上只是对函数作出整理方便读者了解个大概,具体函数功能如何下面将会一一讲解。
主要文件打开方式
文件使用方式 | 含义 | 如果指定文件不存在 |
“r”(只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
“w”(只写) | 为了输出数据,打开一个文本文件(会把文本里原来的内容清空哦) | 建立一个新的文件 |
“a”(追加) | 向文本文件尾添加数据 | 建立一个新的文件 |
“rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
“wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
“ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
“r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,建议一个新的文件 | 建立一个新的文件 |
“a+”(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
“rb+”(读写) | 为了读和写打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
“ab+”(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
不用记,把"r" "w" "a"这三个理解透彻就能融会贯通啦,多说一嘴,有"b"的话就是打开二进制文件。
fopen()与flcose()
ANSIC 规定使用fopen函数来打开文件,fclose函数来关闭文件。
FILE *fopen( const char *filename, const char *mode )
fopen()有两个参数,第一个参数filename代表文件名,第二个形参mode表示文件打开方式。
int fclose( FILE *stream )
函数fclose()返回一个整形数值,当文件关闭成功时,返回0值,否则返回一个非0值。参考代码如下:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL)
{
return 0; //又出现了判断文件打开成功与否
}
fclose(pf);
pf = NULL;
return 0;
}
如上所示,为什么要判断文件打开成功与否呢?跟上篇动态内存分配类似,是因为文件并不是每次都能呗成功地打开的。例如,当文件不存在或者已经损坏时,文件打开就会失败。这是一个至关重要的点!
fgetc()与fputc()
int fgetc( FILE *stream )
fgetc()用于从一个只读或读写方式打开的文件上读字符,该函数较为简单,用法如下:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
return 0;
}
int ch = fgetc(pf);
printf("%c", ch);
ch = fgetc(pf);
printf("%c", ch);
ch = fgetc(pf);
printf("%c", ch);
fclose(pf);
pf = NULL;
return 0;
}
实现前:在文本输入x个字符
实现后:文本上的字符就会呗读取到控制台上
int fputc( int c, FILE *stream )
fputs()用于将一个字符写到一个文件上。用法如下:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
if (pfWrite == NULL)
{
return 0;
}
fputc('b', pf);
fputc('i', pf);
fputc('t', pf);
fclose(pf);
pf = NULL;
return 0;
}
实现前:
实现后:
fgetc()和fputc()还能同时使用
#include <stdio.h>
int main()
{
int ch = fgetc(stdin);
fputc(ch, stdout);
return 0; //你输入什么它就输出什么
}
fgets()与fputs()
char *fgets( char *string, int n, FILE *stream )
fgets()作用是从文件中读取字符串,它的三个参数可以这样理解:第一个参数是dest(目的地),第二个是读取字符的个数,第三个是src(源头)。大致用法如下:
#include <stdio.h>
int main()
{
char arr[1024] = { 0 };
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
return 0;
}
fgets(arr, 1024, pf);
puts(arr); //相当于printf("%s", arr);
fgets(arr, 1024, pf);
puts(arr);
fclose(pf);
pf = NULL;
return 0;
}
操作过程大致如fgetc(),留给读者自行操作检验。
int fputs( const char *string, FILE *stream )
fputs()函数第一个参数想是要输入的字符串,第二个参数是目标文本。大致用法如下:
#include <stdio.h>
int main()
{
char buf[1024] = { 0 };
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
return 0;
}
fputs("hello", pf);
fputs("zjr", pf);
return 0;
}
操作过程大致如fputc(),留给读者自行操作检验。
fread()与fwrite()
这两个函数是用于一次读取一组数据,即按数据块读写文件的。
size_t fread( void *buffer, size_t size, size_t count, FILE *stream )
fread()函数第一个参数是待读入数据块的起始地址,第二个参数是size是每个数据块的大小,第三个参数是最多允许读取的数据块的个数,函数返回的是实际读到的数据块个数。
size_t int fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
fwrite()函数第一个参数是待输出数据块的起始地址,第二个参数是size是每个数据块的大小,第三个参数是最多允许写入的数据块的个数,函数返回的是实际写入的数据块个数。
fseek()与ftell()
这两个函数能实现文件的随机读写,理解难度不大。
int fseek( FILE *stream, long offset, int origin ) offset是长整型位移量
long ftell( FILE *stream )
查询MSDN可知fseek()有三种用法:
SEEK_CUR->光标定位到当前位置
SEEK_END->光标定位到字符串末尾
SEEK_SET->光标定位到字符串开头 (关于光标是什么我将在不久的将来为大家讲解)
话不多说,上代码:
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
return 0;
}
fgetc(pf);
int pos = ftell(pf);
printf("%d\n", pos);
fseek(pf, 5, SEEK_SET);
pos = ftell(pf);
printf("%d\n", pos);
fclose(pf);
pf = NULL;
return 0;
}
看到这的小伙伴建议自己去操作体会一下,真的一操作就清晰明了啦。
关于被错误使用的feof()
在文件读取过程中,不能用feof()函数的返回值直接用来判断文件的是否结束,而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束
1.文本文件读取是否结束,判断返回值是否为EOF(fgetc),或者NULL(fgets)。
e.g: ·fgetc()判断是否为EOF;
·fgets()判断返回值是否为NULL;
2.二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
e.g:fread()判断返回值是否小于实际要读的个数。
尾声
感谢能阅读到者的你,以上就是我对文件操作的浅论,有些未解释到的函数由于鄙人现阶段能力不足无法作出对应讲解,未来将会发布文件操作进阶版。希望我的这篇文章能够帮助到将要学文件操作或者正在学的文件操作的你。如果你觉得这篇文章对你理解文件操作有帮助的话,请留下你的收藏与点赞哦。