一、根据数据的存储方式,文件可为分二进制文件和文本文件:
1、文本文件:ASCLL文件,每个字节存放一个ASCLL码字符,其存储量大,速度慢,便于对字符操作;
2、二进制文件:数据按其在内存中存储形式原样存放,其存储容量小,速度快,便于存放中间结果;
二、根据应用程序对文件的访问方式,即是否存在缓冲区。
1、缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区;如ANSI标准的I/O函数
2、非缓冲文件系统:低级文件系统,由程序为每个文件设定缓冲区。 如POSIX标准的系统调用I/O函数
非缓冲文件系统损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率将造成很大的影响。
三、缓冲区类型
1.全缓冲:要求填满整个缓冲区后才进行I/O系统调用。磁盘文件常用次方式,第一次执行I/O操作,ANSI标准的文件管理函数调用malloc函数获得使用缓冲区,默认大小8196字节;
2.行缓冲:在输入或者输出时遇到换行符,标准I/O库执行系统调用。涉及一个终端如标准输入或者输出,即使没有 遇到换行符也执行系统调用,默认行缓冲大小158字节;
3.无缓冲:如果标准I/O函数写若干字符到不带缓冲区的流中,则相当于用write系统调用函数将这些字符写到相关联的打开文件中。如标准的出错流通常不带缓冲,以便出错信息及时的显示出来。如标准出错流stderr。
四、相关函数
1、void setbuf(FILE *steam, char *buf);
说明:setbuf函数具有打开和关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ(定义在stdio.h头文件中)的缓冲区。通常在此之后该流就是全缓冲的,但是如果该流与一个终端设备相关,那么某些系统也可以将其设置为行缓冲。为了关闭缓冲,可以将buf参数设置为NULL。
2、int setvbuf(FILE *stream, char *buf, int type, unsigned size);
参数:stream :指向流的指针 ;
buf : 期望缓冲区的地址;
type : 期望缓冲区的类型:
_IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数 据。
_IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据。
_IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区。
size : 缓冲区内字节的数量。
3、FILE * fopen(const char * path,const char * mode);
返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno 中。
4、int fclose(FILE *stream);
功 能: 关闭一个流。注意:使用fclose()函数就可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区。
5、int fflush (FILE *_stream)
更新缓冲区内容
6、字符读操作:每次从标准I/O调用只读流中的一个字符
int fgetc(FILE *_stream);
int get(FILE *_stream);
getchar (void); //从标准输入流中读入一个字符。
7、字符写操作:每次从标准I/O调用中只写一个字符到流中
int fputc(int _c , FILE *_stream); //写字符c到流stream 中
int putc(int _c , FILE *_stream);
putchar(int _c) ;向标准输出流中写一个字符
8、行读出操作
char *fgets(char *s, int n, FILE *stream);
参数:
*s: 字符型指针,指向将存储到的数据地址。
n: 整型数据,将从流中读取 n - 1 个字符。
*stream: 指针数据,欲读取的流。
功能:
从文件指针stream中读取n-1个字符,存到以s为起始地址的空间里,直到读完一行,如果成功则返回s的指针,否则返回NULL。
9、行写入操作
int fputs(char *str, FILE *fp);
参数: str是字符型指针,可以是字符串常量,或者存放字符串的数组首地址。
fp是文件型指针,通过打开文件函数fopen()获得的。
功 能:向指定的文件写入一个字符串(不自动写入字符串结束标记符‘\0’)。成功写入一个字符串后,文件的位置指针会自动后移,函数返回值为0;否则返回EOF(符号常量,其值为-1)。
int puts(char *string); //输出流到标准输出设备中
用来向标准输出设备(屏幕)写字符串并换行,其调用方式为,puts(s);其中s为字符串字符(字符串数组名或字符串指针),送一字符串到流stdout中。
10、块读出操作
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
buffer 用于接收数据的内存地址,大小至少是 size*count 字节.
size 单个元素的大小,单位是字节
count 元素的个数,每个元素是size字节.
stream 输入流
返回值: 实际读取的元素数.如果返回值与count(不是count*size)不相同,则可能文件结尾或发生错误. 从ferror和feof获取错误信息或检测是否到达文件结尾.
功 能: 从一个文件流中读数据,读取count个元素,每个元素size字节.如果调用成功返回count.如果调用成功则实际读取size*count字节
11、块写入操作
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); //向文件写入一个数据块
返回值:返回实际写入的数据块数目
(1)buffer:是一个指针,对fwrite来说,是要输出数据的地址;
(2)size:要写入内容的单字节数;
(3)count:要进行写入size字节的数据项的个数;
(4)stream:目标文件指针;
(5)返回实际写入的数据项个数count。
12、文件流定位
long ftell(FILE *stream); //返回当前文件位置,也就是说返回FILE指针当前位置。
int fseek(FILE *stream, long offset, int fromwhere); //修改当前读写位置
第一个参数stream为文件指针
第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END依次为0,1和2.
13、重置当前读写位置
void rewind(FILE *stream); //将文件内部的位置指针重新指向一个流(数据流/文件)的开头
五、格式化输入/输出函数操作
1、int printf(const char *format,[argument]); //将输出按指定格式放置在标准输出流stdout 上
2、int scanf( const char *format, ... ); //格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。
3、int fprintf(FILE *stream,char *format,[argument]) //输出按指定格式放置在指定的输出流上
4、int fscanf(FILE *stream, char *format,[argument...]); //从指定的输入流中按指定的格式读取数据
5、int sprintf( char *buffer, const char *format, [ argument] … ); //格式化的数据写入某个字符串中
buffer:char型指针,指向欲写入的字符串地址。
format:char型指针,指向的内存里面存放了格式字符串。
[argument]...:可选参数,可以是任何类型的数据。
eg:连接字符串 返回值:字符串长度(strlen)
char* who = "I";
char* whom = "CSDN";
sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. "
6、 int sscanf(const char *buffer,const char *format,[argument ]...); //从一个字符串中读进与指定格式相符的数据.
sscanf与scanf类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。
sscanf可以从字符串中取出整数、浮点数和字符串等。
1)、常见用法。
char buf[512] ;
sscanf("123456 ", "%s", buf);//此处buf是数组名,它的意思是将123456以%s的形式存入buf中!
printf("%s\n", buf);
结果为:123456
2). 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf("123456 ", "%4s", buf);
printf("%s\n", buf);
结果为:1234
3). 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf("123456 abcdedf", "%[^ ]", buf);
printf("%s\n", buf);
结果为:123456
4). 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s\n", buf);
结果为:123456abcdedf
当输入:
sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf);
printf("%s\n",buf);
结果为:123456
5). 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s\n", buf);
结果为:123456abcdedf
6)、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
printf("%s\n", buf);
结果为:12DDWDFF
7)、给定一个字符串"hello, world",仅保留world。(注意:","之后有一空格,%s遇空格停止,加*则是忽略第一个读到的字符串)
sscanf("hello, world", "%*s%s", buf);
printf("%s\n", buf);
结果为:world
%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
如果没有空格则结果为NULL。
sscanf的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式.