C语言文件操作总结
- 格式:pdf
- 大小:506.72 KB
- 文档页数:13
C语言文件操作总结
1 文件
文件代表字节序列。fopen()函数将一个文件和流关联起来,并初始化一个类型为FILE的对象,此对象包含控制此流的所有信息。这样的信息包括指向缓冲区的指针、文件读写位置的指针,以及指示错误和文件尾情况的标志。 打开文件的每个函数都会返回“指向FILE对象的指针”,此FILE对象包含此文件的流。一旦打开文件,就可以调用函数对数据和流进行处理。处理函数都需要把FILE指针当自变量。 I/O链接库也包含了“作用于文件系统”的函数,并且这些函数需要把文件文件名作为参数。使用这些函数不需要事先打开文件。函数包括: remove()函数:删除一个文件(或者空目录); rename()函数:改变文件(或目录)的名称,自变量分别为旧文件名和新文件名; 这两个函数的返回值都是int类型,成功是返回0,失败时返回非0值。
2 缓冲区
2.1 缓冲方式
处理文件时,读写个别字符通常效率不佳,因此,流有缓冲区。缓冲区可以把许多字符集中起来,这些字符会以内存区域的方式“整体”进入文件。 流的三种缓冲方式: (1)全缓冲 只有在缓冲区满时缓冲区内的字符才会被正常地转移。 (2)行缓冲 只有当换行字符被写入缓冲区,或者缓冲区满了,缓冲区内的字符才会被正常转移。 (3)无缓冲 字符会尽快地被转移。
2.2 缓冲区的刷新
在C中可以调用fflush()函数显示地把缓冲区内的字符转移到相关文件。在C++中,可以使用flush操作符进行缓冲区的强制刷新;也可以使用endl操作符,它不但实现换行操作,也对输出缓冲区进行刷新。
2.3 改变缓冲模式
当使用fopen()打开一个正常的文件时,新的流是“全缓冲的”。当打开互动设备是,设备文件会被关联到“行缓冲”流。 在打开文件之后,并且在进行第一次输入或输出之前,可以使用setbuf()或setvbuf()函数来改变缓冲模式。 1)void setbuf(FILE *steam, char *buf); 主要用于打开和关闭缓冲机制。 2) int setvbuf(FILE *stream, char *buf, int type, unsigned size); 参数:stream :指向流的指针 ; buf : 期望缓冲区的地址; type : 期望缓冲区的类型: _IOFBF(满缓冲):当缓冲区为空时,从流读入数据。或者当缓冲区满时,向流写入数 据。 _IOLBF(行缓冲):每次从流中读入一行数据或向流中写入一行数据。 _IONBF(无缓冲):直接从流中读入数据或直接向流中写入数据,而没有缓冲区。 size : 缓冲区内字节的数量。
3 标准的流
每个C程序一开始就有三个标准流可以用。这些流不需要被显示得打开。表1-1列出了他们的FILE指针。
表1-1. 标准的流 FILE指针 常用名称 缓冲模式 stdin 标准输入 行缓冲 stdout 标准输出 行缓冲 stderr 标准错误输出 无缓冲 stdin流通常关联到键盘,stdout和stderr则关联到显示器。这些关联可以利用“重定向”的方式来改变。可以通过freopen()函数重新定向,或者程序执行时
操作系统也可以进行重新定向。
4 打开和关闭文件
4.1 打开文件
标准链接库提供fopen()函数来打开文件。特殊情况下,还可以使用freopen()和tmpfile()函数来打开文件。 1)FILE *fopen( const char* restrict filename, const char* restrict mode ); filename为要打开的文件名,也可以包含目录信息;mode指定文件访问方式。 2)FILE *freopen( const char* restrict filename, const char* restrict mode, FILE* restrict stream ); freopen()不会建立新流,而是将此文件和既有的流(第三个自变量)关联起来。之前和此流有关联的文件会被关闭。 3)FILE* tmpfile(void); 建立一个新的临时性文件,名称和所有的既有文件名都不一样,然后打开这个文件,进行数据读写操作(类似于fopen()函数的“wb+”访问模式)。程序正常结束时,此文件被自动删除。 上述的三个函数都会返回一个指针,如果成功就返回FILE指针,失败返回空指针。
4.2 文件访问模式
访问模式确定流的输入和输出操作。 模式 模式说明 “r” 只读 “r+” 读写 “w” 只写 “w+” 读写,存在则清空,不存在创建新的,指针指向文件首 “a” 追加,存在指针指向尾,不存在创建新的 “a+” 追加,存在清空,不存在创建新的 注:加“b”表示打开为是二进制文件而不是纯文本文件。 (根据数据的组织形式,文件可以分为文本文件和二进制文件。文本文件也称ASCII文件,每个字节存放一个ASCII字符。二进制文件是将数据按在内存中的存储形式存放到磁盘上。)
4.3 关闭文件
int fclose( FILE* fp); 返回0表示成功,返回EOF表示错误。
5 文件的读写操作
5.1 字节导向和宽字符导向
除char类型外,C语言也支持宽字符类型wchar_t。对应之下,有两大类函数可以进行字符串和字符的输入和输出:字节字符I/O函数、宽字符I/O函数。宽字符I/O函数用来处理wchar_t类型的字符。每个流都有导向功能,决定哪一类函数才是合适的。 打开文件时并未决定其流的导向。第一个存取动作使用的函数类型将决定流的导向:如果第一个存取动作使用“字节字符I/O函数”,从此以后,此流变成字节导向的,如果第一个存取动作使用“宽字符I/O函数”,那么从此以后,此流变成宽字符导向的。标准流的导向也与此类似。 在任何时候都可以调用fwide()函数来确定某个流的导向。在第一个I/O操作之前,也可以使用fwide()设定一个新流的导向。当固定流的导向后,如果想改变流的导向必须先使用freopen()函数重新打开该流。
5.2 读写字符
5.2.1 读取字符 int fgetc( FILE* fp ); int getc( FILE* fp ); int getchar( void ); wint_t fgetwc( FILE* fp ); wint_t getwc( FILE* fp ); wint_t getwchar( void ); 1)fgetc()函数从输入流fp读取一个字符。返回值是读入的字符,错误时返回EOF; 2)getc()宏和fgetc()函数具有相同的效果。它比调用函数更快,但如果fp是一个“具有副作用”的表达式,宏可能会多次计算自变量,此时应该使用函数版本; 3)getchar()宏从标准输入读取字符,等同于getc(stdin);
4)后三个是宽导向流对应的函数和宏。
5.2.2 放回一个字符 int ungetc( int c, FILE* fp ); wint_t ungetc( wint_t c, FILE* fp ); 1)将最后一个读进来的字符c放回输入流fp中; 2)后进先出; 3)成功时返回放入的字符,失败返回EOF(或WEOF)。
5.2.3 写入字符 int fputc( int c, FILE* fp ); int putc( int c,FILE* fp ); int putchar( int c ); wint_t fputwc( wchar_t wc, FILE* fp ); wint_t putwc( wchar_t wc, FILE* fp ); wint_t putwchar( wchar_t wc ); 与读取字符函数相对应。
5.3 读写字符串
5.3.1 读取字符串 char* fgets( char* buf, int n, FILE* fp ); char* gets( char* buf ); wchar_t* fgetws( wchar_t* buf, int n, FILE* fp ); 1)fgets()和fgetws()会从fp流中读取最多n-1个字符,放进buf缓冲区,然后在后面附加一个空字符作为字符串结束标志。如果此函数在读进最大个数的字符前,遇到一个换行符,或者文件结尾,那么只有目前所读的字符会被放进此缓冲区。如果读取到换行符‘\n’(或者宽导向流的L‘\n’),此字符也会被放入缓冲区中。 2) gets()从标准输入读取一行文字,放到buf缓冲区内。结束此行的换行符在缓冲区中会被空字符取代。fgets()适合取代gets(),因为gets()无法限制读取字符的个数。没有宽字符版本的gets()函数。 3) 三个函数都会返回它们的自变量值buf,失败或者没有字符可以读取时返回NULL。
5.3.2 写入字符串 int fputs( cosnt char* s, FILE* fp ); int puts( const char* s ); int fputws( cosnt wchar_t* s, FILE* fp ); 1)fputs()和fputws()会把字符串s写入fp的输出字符串内。表示字符串结束的空字符不会被写入输出流中。 2)fputs()将字符串s写进标准输出流中,后面跟着一个换行字符。此函数没有对应的宽字符版本。 3)如果发生错误,三个函数都会返回EOF(不是WEOF);成功返回非负的值。
5.4 读写区域
5.4.1 读取区域 size_t fread( void* buffer, size_t size, size_t n, FILE* fp ); fread()函数从fp流中读取最多n个对象,对象空间的大小为size,将这些对象存储在buffer所指向的数组中。 此函数的返回值是被传输的对象个数。如果返回值小于n,就表示读取到了文件尾端,或者发生错误了。
5.4.2 写入区域 size_t fwrite( void* buffer, size_t size, size_t n, FILE* fp ); fwrite()函数把n个对象的数组,每个对象空间大小为size,数组地址是buffer,写入fp流。 此函数的返回值是被写入的对象个数。返回值如果小于n,就表示发生错误。 因为fread()和fwrite()函数没有处理字符或字符串,所以没有宽导向流版本的对应函数。
6 重定位流上的文件内部位置指针
6.1 fseek()-ftell()-rewind()
(1)int fseek(FILE *stream, long offset, int fromwhere);
a)功能:重定位流(数据流/文件)上的文件内部位置指针 b)stream:文件流; offset:偏移量; formwhere:起始位置 c)formwhere SEEK_SET:文件开头 SEEK_CUR:当前位置 SEEK_END:文件结尾 d)返回值:成功0,失败-1 (2)long ftell(FILE *stream); a)功能:返回当前文件位置,也就是说返回FILE指针当前位置 b)fseek()和ftell()结合能方便知道一个文件的长度(文件包含的字节数) (3)void rewind(FILE *stream); a)功能:将文件内部的位置指针重新指向一个流(数据流/文件)的开头 b)rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET);