与操作系统独立,只能操作常规文件,有缓冲区
常规文件:ASCII码文件(文本文件)、二进制文件

缓冲区:减少用户和内核切换的次数,减小系统开销。当对文件进行操作时,缓冲区才会被开辟。当进程结束时自动调用fclose(),关闭已打开的文件,刷新缓冲区。

全缓冲:4k字节,用于标准文件操作,当缓冲区满的时候给内核。

行缓冲:1k字节,用于标准输入输出,当缓冲区遇到‘\n’时给内核。

不带缓冲:0字节,用于标准出错,数据不经过缓冲区,直接给内核。

内核中有高速缓存,定时刷新至硬盘。


描述     文件描述符int    文件描述符对应的宏   文件指针FILE*
标准输入        0            STDIN_FILENO         stdin
标准输出        1            STDOUT_FILENO        stdout
标准错误        2            STDERR_FILENO        stderr


int fflush(FILE *fp); 用于将缓冲区中的数据实时刷新至内核。

FILE *fopen(const char *path,const char *mode);
FILE *fdopen(int fd,const char *mode);   //联系流与文件描述符
FILE *freopen(const char *path,const char *mode,FILE *stream);  //用于重定向
int fclose(FILE *stream);
当一个进城正常终止时(直接调用exit函数,或从main函数返回),系统会自动调用fclose()函数,刷新所有缓冲区,所有打开的标准I/O流都被关闭。
为了编程规范,使用文件后,一定要显式的调用fclose()。 


mode参数:
r或rb      打开只读文件,该文件必须存在。
r+或rb+    打开可读写的文件,该文件必须存在。
w或wb      打开只写文件,若文件存在则清空。若文件不存在则创建该文件。
w+或wb+    打开可读写文件,若文件存在则清空,若文件不存在则创建该文件。
a或ab      以附加方式打开只写文件,若不存在则创建,若文件存在,写入的数据追加到文件尾,即原先内容被保留。
a或ab+     以附加方式打开可读写文件,若不存在则创建,若文件存在,写入的数据追加到文件尾,即原先内容被保留。
b 表示以二进制方式打开文件。

二进制和文本模式的区别

1.在windows系统中,文本模式下,文件以"\r\n"代表换行。若以文本模式打开文件,并用fputs等函数写入换行符"\n"时,函数会自动在"\n"前面加上"\r"。即实际写入文件的是"\r\n" 。

2.在类Unix/Linux系统中文本模式下,文件以"\n"代表换行。所以Linux系统中在文本模式和二进制模式下并无区别。


每次一个字符的I/O:如果流是带缓冲的,标准I/O函数处理所有缓冲。
int fgetc(FILE *stream);  文件结尾或出错都返回EOF
while(!feof(fp)&&!ferror(fp))
{

    ch = fgetc(fp);
    if(ch == EOF) break;
    printf("%c",ch);
}
int fputc(int c,FILE *stream);

int getc(FILE *stream);

int putc(FILE *stream);

实现为宏,从流中读或写。

int getchar(void); 从终端读 stdin

int putchar(int c); 输出到终端 stdout

实现为宏

检查文件出错函数

int feof(FILE *stream);

int ferror(FILE *stream);

int clearerr(FILE *stream);


每次一行的I/O:每行都以‘\n'结束
char *fgets(char *s,int size,FILE *stream);已处文件尾端或出错返回NULL。
fgets一次只能从文件读取一行(一行最大1024个字节),在文本文件中,每行最后都是‘\n’,fgets会自动读取最后的换行符,所以打印时不需加‘\n'。
当用fgets读取n个字节的数据时,只会返回n-1个字符,最后一个放‘\0’。
while(fgets(str,100,fp1) != NULL)
{
    fputs(str,fp2);
}
int fputs(const char *s,FILE *stream);

char *gets(char *s);int puts(const char *s);


直接I/O:用于读写块或结构体
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
从流stream中读取size*nmemb个字节到ptr开始的地址空间。
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);


定位流:
int fseek(FILE *stream, long offset, int whence); 用于设定流的文件位置。offset为正向后偏移,为负向开头偏移。whence参数为 SEEK_SET(开头)/SEEK_CUR(当前)/SEEK_END(结束)。
long ftell(FILE *stream); 获取当前的文件位置。
void rewind(FILE *stream); 用于设定流的文件位置为文件开始。