作为一个大三的学生,在实习过程中接触到的第一个任务,融合终端APP的日志保存功能。我尽可能详细的写出了整个的思考和设计过程,因为本人并不是计算机专业,所想所写如有错误,望更正!
1.3.1任务要求
要求:写一个函数,设置三个文件log1,log2,log3,限制每个文件的大小不超过2M(log1写入的内容超过2M时,写入log2中,log2写入的内容超过2M时,写入log3中,log3写入的文件超过2M时,清空log1写入log1中,如此循环),整个日志的大小不超过6M。
1.3.2程序逻辑
先写入log1中,写满之后重命名,写入log2中,log2写满之后写到log3中,log3 满了之后将log1清空重新写入log1中,如此循环……
1.3.3设计思路
首先提出了三个关键性的问题。
(1)日志是如何写入的?
(2)日志文件大小的限制函数,怎样判断一个log的大小已经到达2M?
(3)相关函数:
fopen的函数原型为: FILE *fopen(const char *filename, const char *mode);其功能是使用给定的模式 mode 打开 filename 所指向的文件。文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回 NULL,并把错误代码存在 error 中。该函数位于C 标准库<stdio.h>中。
函数原型:
FILE *fopen(const char *filename, const char *mode);
参数:
filename-- 这是 C 字符串,包含了要打开的文件名称。
mode-- 这是 C 字符串,包含了文件访问模式。
注意:
(1)用"r"方式打开的文件,不能向其输入数据,并且该文件已存在,否则出错;
(2)用"w"方式打开的文件,只能向该文件输入数据,如果所打开的文件不存在,则在打开时新建一个以指定的名字命名的文件;如果指定文件存在,则在打开时将该文件删去,然后新建一个新的文件;
(3)如果函数fopen打开文件出错,则fopen返回一个空指针值NULL;
(4)在程序开始运行时,系统自动打开3个标准文件:标准输入(stdin),标准输出(stdout),标准出错输 出(stderr)。如果要使用输入输出终端,则不需要打开,可以直接使用,如fputc(stdout,'a');向屏幕输出字符a。
1.3.4错误总结
错误1:日志写入不成功!
原因:①只写了fopen()文件打开函数,而没有写fclose()文件关闭函数。总结:使用fopen()打开的文件,一定要记得使用fclose()关闭,否则会出现很多意想不到的情况,例如对文件的更改没有被记录到磁盘上,其他进程无法存取该文件等。
②fopen(打开文件的名称,文件访问的模式),注意文件的访问模式,要求可读可写!
错误2:读取位置时发生访问冲突!
原因:(1)可能是栈溢出,解决方法:扩大栈空间的大小,在vs工程里面:项目->属性->链接器->系统->堆栈保留大小(注:这里填的是字节数)。若为2M的话,则保留大小为1024*1024*2 = 2097152
(2)语句的参数有误
①fopen文件的访问模式,”wb+” 改为 “r+”。
②fwrite函数,第一个参数位置要写指针。
错误3:循环跳不出去!
判断相等用 == ,若用=是赋值,一直循环赋值!
错误4:txt文件的重命名不成功!
上述的第一条,使用rename(“old name”,“new name”)函数之前要先关闭log1才能够实现:fclose(pf1);跟平常对文件重命名要先关闭文件一样
1.3.5代码
#define _CRT_SECURE_NO_WARNINGS
#include <time.h>
#include<stdio.h>
#include<errno.h>
#include <sys/timeb.h>
#include<string.h>
#define FILE_MAX_SIZE 2 * 1024 * 1024 //一个字母字符占一个字节
#define LOG_FILE_COUNT 3 // 日志文件的数量
void saveLog(const char* filename, const char* loginfo)
{
char timebuf[21];// 字符串形式保存时间
time_t ltime;// 时间戳
struct tm today;// 本地时间结构体
FILE* pf1 = fopen(filename , "a+"); //"a+ ":可读/写,在文件尾追加
fseek(pf1, 0, SEEK_END); //fseek函数 pf1指针到文件末尾,向前偏移0个字节
int ret = ftell(pf1); //ftell返回文件的大小,单位:字节
char name2[20];
sprintf(name2, "%s %d", filename, 2);
char name3[20];
sprintf(name3, "%s %d", filename, 3);
const char* filename2 = name2;
const char* filename3 = name3;
if (ret > FILE_MAX_SIZE)
{
fclose(pf1);
remove(filename3);
rename(filename2 , filename3 );
rename(filename, filename2);
FILE* pf1 = fopen(filename, "a+"); //"a+ ":可读/写,在文件尾追加
fprintf(pf1, "%s\n", loginfo);
char buffer[4096];
struct timeb tTimeB;
ftime(&tTimeB);//获取当前的秒数和毫秒数
struct tm* tTM = localtime(&tTimeB.time);//将秒数转为时间格式
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d:%03d\r\n", tTM->tm_year + 1900,
tTM->tm_mon + 1, tTM->tm_mday, tTM->tm_hour, tTM->tm_min, tTM->tm_sec,
tTimeB.millitm);
fwrite(buffer, 25, 1, pf1);
fclose(pf1);
}
else
{
fprintf(pf1, "%s\n", loginfo);
char buffer[4096];
struct timeb tTimeB;
ftime(&tTimeB);//获取当前的秒数和毫秒数
struct tm* tTM = localtime(&tTimeB.time);//将秒数转为时间格式
sprintf(buffer, "%04d-%02d-%02d %02d:%02d:%02d:%03d\r\n", tTM->tm_year + 1900,
tTM->tm_mon + 1, tTM->tm_mday, tTM->tm_hour, tTM->tm_min, tTM->tm_sec,
tTimeB.millitm);
fwrite(buffer, 25, 1, pf1);
fclose(pf1);
}
}
int main()
{
char filename[10] = "读后感";
char loginfo[1024] = "Thecontinuousstruggleistogoontheroadtosuccess.";
saveLog(filename, loginfo);
return 0;
}