目录
前言
文件的打开和关闭的概念
文件的打开
文件的打开函数
文件打开的模式
文件的关闭
文件的关闭函数
注意事项
字符的输入(读单个字符)
字符输入的函数
注意事项
字符的输出(写单个字符)
字符输出的函数
注意事项
行输入(读取整个行)
行输入的函数
注意事项
行输出(写整行)
行输出的函数
二进制读写
文本文件和二进制的区别
二进制读写函数
注意事项
流的刷新
流的刷新函数
流的定位
流的定位函数
注意事项
判断流是否出错和结束
判断流是否出错和结束函数
格式化输出
格式化输出函数
格式化输入
格式化输入函数
代码练习
要求
具体实现代码
测试结果
总结
前言
上文对标准IO、流及缓冲区的概念进行介绍并进行了相关实验,上文链接点这里,本文来介绍使用标准IO进行文件的打开、关闭、读、写等相关操作。
文件的打开和关闭的概念
打开就是占用资源
关闭就是释放资源
文件的打开
文件的打开函数
FILE *fopen (const char *path, const char *mode);
path:普通文件当前路径不需要加目录,其他要使用完成的路径
mode:文件打开的模式
返回值:出错返回NULL,所以使用fopen函数必须判断是否为空
文件打开的模式
"r"或"rb" | 以只读方式打开文件,文件必须存在。 |
"r+"或"r+b" | 以读写方式打开文件,文件必须存在 |
"w"或"wb" | 以只写方式打开文件,若文件存在则文件长度清为0。若文件不存在则创建。 |
"w+"或"w+b" | 以读写方式打开文件,其他同"w"。 |
"a"或"ab" | 以只写方式打开文件,若文件不存在则创建;向文件写入的数据被追加到文件末尾。 |
"a+"或"a+b" | 以读写方式打开文件。其他同"a"。 |
文件的关闭
文件的关闭函数
int fclose(FILE *stream)
fclose()调用成功返回0,失败返回EOF(-1),并设置errno。
流关闭时自动刷新缓冲中的数据并释放缓冲区,比如:常规文件把缓冲区内容写入磁盘。
当一个程序正常终止时,所有打开的流都会被关闭。
注意事项
fclose()函数的入参stream必须保证为非空,否则出现断错误。
字符的输入(读单个字符)
字符输入的函数
int fgetc(FILE *stream);
int getc(FILE *stream); //宏
int getchar(void);
成功时返回读取的字符,若到文件末尾或出错时返回EOF(-1)。
getchar()等同于fgetc(stdin)
getc和fgetc区别就是一个时宏一个是函数
注意事项
1、函数返回值是int类型不是char类型,主要是为了扩展返回值的范围。
2、stdin也是FILE*的指针,是系统定义好的,指向的是标准输入(键盘输入)。
3、打开文件后读取,是从文件开头开始读,读完一个后读写指针会后移。
4、调用getchar会阻塞,等待你的键盘输入
字符的输出(写单个字符)
字符输出的函数
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
成功时返回写入的字符;出错时返回EOF。
putchar(c)等同于fputc(c, stdout)。
注意事项
1、返回和输入参数都是int类型
2、遇到这种错误:Bad file descriptor, 很可能是文件打开的模式错误(只读模式去写,只写模式去读)
行输入(读取整个行)
行输入的函数
char *gets(char *s); 读取标准输入到缓冲区s
char *fgets(char *s, int size, FILE *stream);
成功时返回s,到文件末尾或出错时返回NULL
遇到’\n’或已输入size-1个字符时返回,总是包含’\0’
注意事项
1、gets函数已经被淘汰,因为会导致缓冲区溢出
2、fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于size-1 后面会添加换行符。
行输出(写整行)
行输出的函数
int puts(const char *s);
int fputs(const char *s, FILE *stream);
成功时返回非负整数;出错时返回EOF
puts将缓冲区s中的字符串输出到stdout,并追加’\n’
fputs将缓冲区s中的字符串输出到stream,不追加 ‘\n’
二进制读写
文本文件和二进制的区别
存储的格式不同:文本文件只能存储文本。
计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字0101001....,所以所有符号都要编码)
二进制读写函数
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
//void *ptr 读取内容放的位置指针
//size_t size 读取的块大小
//size_t n 读取的个数
//FILE *fp 读取的文件指针
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
//void *ptr 写文件的内容的位置指针
//size_t size 写的块大小
//size_t n 写的个数
//FILE *fp 要写的文件指针
注意事项
文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。
解决办法:移动指针(后面讲解)到文件头;关闭文件,重新打开
流的刷新
流的刷新函数
int fflush(FILE *fp);
成功时返回0;出错时返回EOF。
将流缓冲区中的数据写入实际的文件。
Linux下只能刷新输出缓冲区,输入缓冲区丢弃。
如果输出到屏幕使用fflush(stdout)。
流的定位
流的定位函数
long ftell(FILE *stream);
long fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
ftell()成功时返回当前读写位置,出错时返回EOF。
fseek()定位一个流,成功时返回0,出错时返回EOF。
rewind()将流定位到文件开始位置
whence参数:SEEK_SET/SEEK_CUR/SEEK_END
offset参数:偏移量,可正可负
SEEK_SET | 从距文件开头 offset 位移量为新的读写位置 |
SEEK_CUR | 以目前的读写位置往后增加 offset 个位移量 |
SEEK_END | 将读写位置指向文件尾后再增加 offset 个位移量 |
注意事项
1、打开a模式,fseek无效
2、读写流时,当前读写位置自动后移。
判断流是否出错和结束
判断流是否出错和结束函数
#include <stdio.h>
int ferror(FILE *stream);
int feof(FILE *stream);
ferror()返回1表示流出错;否则返回
feof()返回1表示文件已到末尾;否则返回0
格式化输出
格式化输出函数
int fprintf(FILE *stream, const char *fmt, …);
int sprintf(char *s, const char *fmt, …);
成功时返回输出的字符个数;出错时返回EOF。
格式化输入
格式化输入函数
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
代码练习
要求
1、每隔1s以指定格式 “年-月-日” 分别写入文件和缓冲区;
2、该程序无限循环,直到Ctrl+C中断程序;
具体实现代码
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
int main(int argc,const char* argv)
{
FILE *fp;
time_t ctime;
struct tm *ctimester;
int linecount = 0;
char buf[32];
fp = fopen("1.txt","a+");
if(fp == NULL)
{
perror("fopen");
return 0;
}
//calculate 1.txt line
while(fgets(buf,32,fp)!=NULL)
{
if(buf[strlen(buf)-1] == '\n')
{
linecount++;
}
}
while(1)
{
ctime = time(NULL);
ctimester = localtime(&ctime);
printf("%04d-%02d-%02d %02d:%02d:%02d\n",ctimester->tm_year+1900,
ctimester->tm_mon+1,
ctimester->tm_mday,
ctimester->tm_hour,
ctimester->tm_min,
ctimester->tm_sec);
fprintf(fp,"%d, %04d-%02d-%02d %02d:%02d:%02d\n",linecount++,ctimester->tm_year+1900,
ctimester->tm_mon+1,
ctimester->tm_mday,
ctimester->tm_hour,
ctimester->tm_min,
ctimester->tm_sec);
fflush(fp);
sleep(1);
}
fclose(fp);
return 0;
}
测试结果
总结
本文总结了C语言标准IO的输入、输出、读写、流的刷新定位等相关概念及函数介绍,并根据这些函数进行了一个包含文件打开关闭、读写、格式化输出等内容的实现。