格式化日志文件

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了格式化日志文件相关的知识,希望对你有一定的参考价值。

实验内容

编程读写一个文件 test.txt,每隔 1 秒向文件中写入一行数据,类似这样

1, 2021-7-30 15:16:42

2, 2021-7-30 15:16:43

该程序应该无限循环,直到按 Ctrl-C 中断程序。下次再启动程序写文件时可以追加到原 文件之后,并且序号能够接续上次的序号,比如:

1, 2021-7-30 15:16:42

2, 2021-7-30 15:16:43

3, 2021-7-30 15:19:02

4, 2021-7-30 15:19:03

5, 2021-7-30 15:19:0

实验平台

PC 机、ubuntu 操作系统,gcc 等工具

实验提示

  • 首先判断一下打开的文件是否为新文件,如果是新文件,就从序号 1 开始写入;如果不
    是新文件,则统计原来有多少行,比如有 n 行,然后从序号 n+1 开始写入。以后每写一
    行就把行号加 1。
  • 获取当前的系统时间需要调用函数 time(),得到的结果是一个 time_t 类型,其实就是
    一个大整数,其值表示从 UTC 时间 1970 年 1 月 1 日 00:00:00(称为 UNIX 的 Epoch 时
    间)到当前时刻的秒钟数。然后调用 localtime()将 time_t 所表示的 UTC 时间转换为
    本地时间(我们是+8 区,比 UTC 多 8 个小时)并转成 struct tm 类型,该类型的各数
    据成员分别表示年月日时分秒,请自己写出转换格式的代码,不要使用 ctime()或
    asctime()函数。具体用法请查阅man page。time和localtime函数需要头文件time.h。
  • 调用 sleep(n)可使程序睡眠 n 秒,该函数需要头文件 unistd.h。

实验思路

第一种

第一种思路就是按照上面的提示,我们先计算行数,然后一次递增输出即可:

Code:

#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <unistd.h>

int cal_line(FILE *fp) {
    int a[7];
    int lines = 0;
    while(fscanf(fp,"%d, %d-%d-%d %02d:%02d:%02d",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]) != EOF){//格式化读入,当然你也可以用fgets
        lines++;
    }
    return lines;
}
int cal_line_2(FILE *fp) {
    int a[41];
    int lines = 0;
    while(fgets(a,40,fp)){
        lines++;
    }
    return lines;
}

int main() {

    char *path = "a.txt";
    FILE* fp_open = fopen(path,"a+");//以a+打开的话,如果没有文件则会自己创建,并且读取会从第一行开始读
    if(fp_open == NULL) {
        fclose(fp_open);
        perror("open_errot:");
        return -1;
    }
    int lines = cal_line(fp_open);//获取行数
    fclose(fp_open);
    time_t now ;
    struct tm *tm_now ;
    while(1) {
        FILE* fp_write = fopen(path,"a");//从末尾追加
        time(&now);
        tm_now = localtime(&now) ;//get date
        printf("%d, %d-%d-%d %02d:%02d:%02d\\n",lines,tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);//打印到屏幕观察
        fprintf(fp_write,"%d, %d-%d-%d %02d:%02d:%02d\\n",lines++,tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);//输出到文件中
        fclose(fp_write);//关闭文件
        sleep(1);//睡眠1s
    }
    return 0;
}

第二种

其实每次都计算行数在log行数比较多的时候很费时间,所以我们可以每次操作的时候就保存一个当前的行数,我们可以叫这个文件为配置文件c.txt,日志文件为b.txt,这样我们每次获取行数直接读取就行不用计数

Code:

#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <unistd.h>

int main()
{
    char *path_log = "b.txt";//log文件
    char *path_init = "c.txt";//配置文件
    FILE *fp_open = fopen(path_init,"a+");
    int lines = 0;
    if(fscanf(fp_open,"%d",&lines)==EOF) {
        lines = 0;
    }
    fclose(fp_open);
    time_t now ;
    struct tm *tm_now ;
    while(1) {
        time(&now);
        tm_now = localtime(&now) ;//get date
        FILE *fp_write = fopen(path_log,"a+");
        FILE *fp_init = fopen(path_init,"w");
        printf("%d, %d-%d-%d %02d:%02d:%02d\\n",lines,tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
        fprintf(fp_write,"%d, %d-%d-%d %02d:%02d:%02d\\n",lines++,tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
        fprintf(fp_init,"%d\\n",lines);
        fclose(fp_write);
        fclose(fp_init);
        sleep(1);
    }
    return 0;
}

以上是关于格式化日志文件的主要内容,如果未能解决你的问题,请参考以下文章

argparse 代码片段只打印部分日志

varnishlogVarnishstat详解

python常用代码片段总结

如何在 Javadoc 中使用 @ 和 符号格式化代码片段?

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段

我的Android进阶之旅关于Android平台获取文件的mime类型:为啥不传小写后缀名就获取不到mimeType?为啥android 4.4系统获取不到webp格式的mimeType呢?(代码片段