目前主要介绍使用C函数操作文件流,之后待续。。。
读取单个字符操作:
int fgetc (FILE * stream); // 从文件流中读取一个字符。可将标准输入stdin作为参数。 _Check_return_opt_ _CRTIMP int __cdecl fgetc(_Inout_ FILE * _File);
int fputc (int character, FILE * stream); _Check_return_opt_ _CRTIMP int __cdecl fputc(_In_ int _Ch, _Inout_ FILE * _File);
int getc (FILE* stream); // 与fgetc等效 _Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE * _File);
int putc (int character, FILE * stream); _Check_return_opt_ _CRTIMP int __cdecl putc(_In_ int _Ch, _Inout_ FILE * _File);
int getchar (); // 从标准输入stdin读入一个字符。相当于fgetc(stdin)。 _Check_return_ _CRTIMP int __cdecl getchar(void);
int putchar(int character); _Check_return_opt_ _CRTIMP int __cdecl putchar(_In_ int _Ch);
读取字符串操作:
char * fgets (char * str, int num, FILE * stream); // 从文件流中读取最多num个字符到字符数组str中, // 当遇到结束符(如换行符)或者读到num - 1个字符时停止。 // 函数自动在末尾添加 ' ' 空字符。 _Check_return_opt_ _CRTIMP char * __cdecl fgets(_Out_z_cap_(_MaxCount) char * _Buf, _In_ int _MaxCount, _Inout_ FILE * _File);
int fputs(const char * str, FILE * stream); _Check_return_opt_ _CRTIMP int __cdecl fputs(_In_z_ const char * _Str, _Inout_ FILE * _File);
char* gets (char * str); // no commend!!! // 从标准输入stdin中读取字符串,直到遇到结束符为止。 // 该函数未指定大小,所以一定要注意字符数组的大小。 _Check_return_ _CRTIMP char * __cdecl gets(char * _Buffer);
int puts(const char * str); // no commend!!! _Check_return_opt_ _CRTIMP int __cdecl puts(_In_z_ const char * _Str);
早期的Internet蠕虫病毒的实现其中就用到了gets函数。该函数的任务是从文件流中读入一个字符串。调用者将提供读入的字符串存放的位置。但是,该函数并不能检测缓冲区的大小。若调用者提供了一个指向堆栈的指针,并且gets()函数读入的字符串数量超过了缓冲区的大小,该函数会将多出来的字符串继续写入堆栈中,从而覆盖了堆栈中原始内容(缓冲区溢出攻击)。
main () { char buffer[512]; // 在程序堆栈上申请并分配512个字符空间 // ... ... gets(buffer); // 病毒执行入口,可将恶意代码通过溢出覆盖堆栈中原始数据 }
文件结束符:EOF
EOF是在stdio.h文件中定义的常量,值为-1。
fputc函数返回值:执行成功返回值就是输出的字符;失败则返回EOF。
fgetc函数读字符时遇到文件结束符,返回文件结束符EOF。
若从磁盘文件中顺序读取字符并在屏幕上显示:
ch = fgetc(fp); while (ch != EOF) { putchar(ch); ch = fgetc(fp); }
EOF是控制字符,不能在屏幕上显示。由于ASCII编码中不可能出现-1,因此EOF这样定义是合适的。当读入的字符值为-1时,表示读入的已经不是正常的ASCII字符了,这样就可以将-1作为文件结束符。
但这种情况只适用于读取文本文件,目前ASCII已经允许使用缓冲文件系统处理二进制文件,而读入某个字节中的二进制数据时有可能是-1。这样就出现了读取数据却提前结束的情况。
正确的做法是我们要使用feof()函数来测试文件的当前状态是否已经结束。
int feof (FILE * stream); _Check_return_ _CRTIMP int __cdecl feof(_In_ FILE * _File);
ch = fgetc(fp); while (!feof(fp)) { putchar(ch); ch = fgetc(fp); }
参考链接:
http://www.cnblogs.com/duzouzhe/archive/2009/10/24/1589348.html
http://www.jb51.net/article/37688.htm
http://www.blogjava.net/tinysun/archive/2010/07/26/327155.html