利用标准C语言库函数进行文本文件读写
利用C语言进行文件操作的方法有多种。其中包括在UNIX系统环境下利用系统接口进行文件操作;在windows系统下可以利用windows系统下可以利用fopen_s等库函数的安全版本进行文件操作。但是用的最多的就是利用标准库函数进行文件操作。本文主要介绍利用C标准库函数进行文件的打开、读取(一次一个字符、一次一行、格式化读)、写入(一次写入一个字符、一次写一行、格式化写)和关闭操作。其中这些库函数都包含在头文件<stdio.h>中。
启动一个C语言程序时,操作系统环境会打开标准输入、标准输出和标准错误3个文件,相应的文件指针分别为stdin、stdout和stderr(文件指针stdin/stdout都是FILE*类型的对象,但他们是常量而非变量,不能对它们赋值)。在大多数环境中,stdin指向键盘,而stdout和stderr指向显示器。当然也可以被重定向到文件或者管道。
一、文件打开
1、fopen
1)函数原型:
FILE *fopen( const char* filename, const char* mode );
2)参数
第一个参数是一个字符串,它包含文件名。第二个参数也是字符串,表示的是访问模式。允许的模式包括:
“r” |
读 |
如果文件不存在,打开失败 |
"w" |
写 |
如果文件存在,把文件截断至0长;如果文件不存在,会创建文件 |
"a" |
追加 |
如果文件存在,在文件尾进行写;如果文件不存在会创建文件 |
"r+" |
读和写 |
如果文件不存在,打开失败 |
"w+" |
读和写 |
如果文件存在,把文件截断至0长;如果文件不存在,会创建文件 |
"a+" |
读和追加 |
如果文件存在,在文件尾进行写;如果文件不存在会创建文件 |
3)返回值
若打开成功则返回一个指向FILE对象的指针;若打开失败则返回NULL。
(FILE通常是一个结构,它包含了标准I/O库为管理该流需要的所有信息,包括用于实际I/O的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前缓冲区的字符数以及出错标志等。
但是在本例中FILE像int一样是一个类型名,而不是结构标记)
4)示例
#include <stdio.h> FILE *stream, *stream2; void main( void ) { int numclosed; /* Open for read (will fail if file "data" does not exist) */ if( (stream = fopen( "data", "r" )) == NULL ) printf( "The file "data" was not opened " ); else printf( "The file "data" was opened " ); /* Open for write */ if( (stream2 = fopen( "data2", "w+" )) == NULL ) printf( "The file "data2" was not opened " ); else printf( "The file "data2" was opened " ); /* Close stream */ if(fclose( stream2 )) printf( "The file "data2" was not closed " ); /* All other files are closed: */ numclosed = _fcloseall( ); printf( "Number of files closed by _fcloseall: %u ", numclosed ); }执行结果:
二、读文件(读流)
1、一次读一个字符
(1)fgetc
1)函数原型
int fgetc( FILE* stream );
2)返回值
若成功返回下一个字符,若已到达文件尾端或者出错返回EOF;
①返回下一个字符时,将其unsigned char 类型转换为int类型。返回整型的原因是可能会需要返回已出错或已达文件尾端的指示值EOF(通常为-1)。
②不管出错还是到达尾端返回的都是EOF。为了区分这两种情况,可以调用 int ferror(FILE *fp)或者int feof(FILE *fp)来进行判断(若是真返回非0,否则返回0)。
3)示例
#include <stdio.h> #include <stdlib.h> void main( void ) { FILE *stream; char buffer[81]; int i, ch; /* Open file to read line from: */ if( (stream = fopen( "fgetc.c", "r" )) == NULL ) exit( 0 ); /* Read in first 80 characters and place them in "buffer": */ ch = fgetc( stream ); for( i=0; (i < 80 ) && ( feof( stream ) == 0 ); i++ ) { buffer[i] = (char)ch; ch = fgetc( stream ); } /* Add null to end string */ buffer[i] = " "; printf( "%s ", buffer ); fclose( stream ); }
(2)getc
int getc( FILE *stream );getc()与fgetc()使用方法相同。区别是getc可被实现为宏,而fgetc不能实现为宏。
因此:①getc的参数不应该是有副作用的表达式,因为可能会被计算多次 ;
②fgetc是函数,因此可以得到其地址 ;
③fgetc的所需时间可能会比getc要长。
(3)getchar
int getchar( void );getchar用来从标准输入中读取数据;被实现为宏而不是函数。例如:
#define getchar() getc(stdin)
2、一次读一行
(1)fgets
1)函数原型
char *fgets( char* string, int n, FILE *stream );2)参数
string:读取后存放的缓冲区地址;n:缓冲区长度;stream:要读的文件指针
3)返回值
若到达文件尾或者出错返回NULL;
若读取成功返回读取的字符串。其中以行为单位进行读取,读入的字节放入缓冲区。若一行中包括最后一个换行符的字符数大于n-1个;则fgets值返回不完整的行,对fgets的下次调用会继续读该行。缓冲区总是以NULL字节结尾。
4)示例
#include <stdio.h> void main( void ) { FILE *stream; char line[5]; if( (stream = fopen( "fgets.c", "r" )) != NULL ) { while(fgets(line,5,stream)!=NULL) { printf( "%s", line); } printf(" "); fclose( stream ); } }输出(与fgets.c中的文件格式相同):
若只执行一次fgets输出的是:/* f
(2)gets
char *gets( char* buffer );gets从标准输入读,但是不推荐使用该函数。因为gets没有指定缓冲区长度,这样如果一行的长度大于缓冲区的长度就有可能照成缓冲区溢出。
gets与fgets的另一个区别是gets并不将换行符存入缓冲区。
3、格式化读
(1)fscanf
1)函数原型
int fscanf( FILE* stream, const char* format [, argument ]... );2)参数
format:控制如何转换参数,以便对它们赋值。格式与scanf中的格式控制相同。
argument:包含各变量的地址,用转换结果对这些变量赋值。
3)返回值
返回赋值的输入项数;若输入错误(格式不匹配)或任意转换前已经到达文件尾端,返回EOF。
4)示例
#include <stdio.h> FILE *stream; void main( void ) { long l; float fp; char s[81]; char c; stream = fopen( "fscanf.out", "w+" ); if( stream == NULL ) printf( "The file fscanf.out was not opened " ); else { fprintf( stream, "%s %ld %f%c", "a-string", 65000, 3.14159, "x" ); /* Set pointer to beginning of file: */ fseek( stream, 0L, SEEK_SET ); /* Read data back from file: */ fscanf( stream, "%s", s ); fscanf( stream, "%ld", &l ); fscanf( stream, "%f", &fp ); fscanf( stream, "%c", &c ); /* Output data read: */ printf( "%s ", s ); printf( "%ld ", l ); printf( "%f ", fp ); printf( "%c ", c ); fclose( stream ); } }输出:
三、文件写
1、一次写一个字符
(1)fputc
与输入函数fgetc相对应
1)函数原型
int fputc( int c, FILE* stream );2)返回值
若成功返回 c;若出错返回EOF。
3)示例
/* FPUTC.C: This program uses fputc and _fputchar * to send a character array to stdout. */ #include <stdio.h> void main( void ) { char strptr1[] = "This is a test of fputc!! "; char strptr2[] = "This is a test of _fputchar!! "; char *p; /* Print line to stream using fputc. */ p = strptr1; while( (*p != " ") && fputc( *(p++), stdout ) != EOF ) ; /* Print line to stream using _fputchar. */ p = strptr2; while( (*p != " ") && _fputchar( *(p++) ) != EOF ) ; }(2)putc
int putc( int c, FILE *stream );与getc相对应;被实现为宏;fputc不能实现为宏
示例:
/* This program uses putc to write buffer * to a stream. If an error occurs, the program * stops before writing the entire buffer. */ #include <stdio.h> int main( void ) { FILE *stream; char *p, buffer[] = "This is the line of output "; int ch; ch = 0; /* Make standard out the stream and write to it. */ stream = stdout; for( p = buffer; (ch != EOF) && (*p != " "); p++ ) ch = putc( *p, stream ); }(3)putchar
与getchar想对应;putchar(c)等同于putc(c,stdout);被实现为宏
2、一次写一行
(1)fputs
与fgets相对应
1)函数原型
int fputs( const char* string, FILE* stream );2)返回值
若成功返回非负值,若失败返回EOF
fputs将以NULL字节终止的字符串写到指定的流;尾端的终止符NULL不写出。注意:这并不是每次每次输出一行,因为字符串 不需要换行符作为最后一个非NULL字节。
3)示例
/* FPUTS.C: This program uses fputs to write * a single line to the stdout stream. */ #include <stdio.h> void main( void ) { fputs( "Hello world from fputs. ", stdout ); }(2)puts
与gets相对应。
int puts( const char* string );puts将一个以NULL字节终止的字符串写到标准输出,终止符不写出。但是随后会将一个换行符写到标准输出。
与gets不同puts是安全的。但是要注意最后添加的换行符。
3、格式输出
(1)fprintf
与fscanf相对应
1)函数原型
int fprintf( FILE* stream, const char* format [, argument ]... );将数据格式化写字stream流
2)示例
/* FPRINTF.C: This program uses fprintf to format various * data and print it to the file named FPRINTF.OUT. */ #include <stdio.h> FILE *stream; void main( void ) { int i = 10; double fp = 1.5; char s[] = "this is a string"; char c = " "; stream = fopen( "fprintf.out", "w" ); fprintf( stream, "%s%c", s, c ); fprintf( stream, "%d ", i ); fprintf( stream, "%f ", fp ); fclose( stream ); }
四、文件关闭
1、fclose
(1)函数原型
int fclose( FILE* stream );(2)返回值
如果成功关闭返回0;若出错返回EOF.
(3)说明
在文件被关闭之前,会冲洗缓冲中的输出数据。缓冲区中的任何输入数据被丢弃。如果标准I/O库已经为该流自动分配了一个缓冲区,则释放此缓冲区。
2、_fcloseall
(1)函数原型
int _fcloseall( void );(2)返回值
如果成功则返回关闭的流的数目;失败时返回EOF
(3)说明
函数会关闭除stdin、stdout以及stderr外的所有文件流;其中包括由tepfile创建的临时文件。
1、MSDN
2、《UNIX环境高级编程》
3、《C程序设计语言》
- 上一篇:没有了
- 下一篇:没有了