纯c语言简单的写日志文件方法,gcc编译即可

概述

本文案例基于一个已有的C语言模块,该模块在之前的版本中并未包含文件日志功能。我们的目标是通过添加一个简单的日志记录方法,使得模块能够在运行时将关键信息写入到日志文件中。为了保证通用性,我们将支持Windows和Linux操作系统,并且涵盖x86和ARM架构的适配。

完整代码分析与优化

以下是我们将要优化和扩展的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#define FILE_MAX_SIZE (1024 * 1024)

/*
获得当前时间字符串
@return 当前时间字符串
*/
char* get_local_time_with_ms() {
  struct timeval tv;
  gettimeofday(&tv, NULL);

  struct tm* timeinfo = localtime(&tv.tv_sec);

  char* now = malloc(32);
  if (now != NULL) {
    snprintf(now, 32, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", (timeinfo->tm_year + 1900), timeinfo->tm_mon + 1,
             timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
             tv.tv_usec / 1000);  // 毫秒信息,微秒除以1000得到毫秒
  }
  return now;
}

/*
获得文件大小
@param filename [in]: 文件名
@return 文件大小
*/
long get_file_size(char* filename) {
  long length = 0;
  FILE* fp = NULL;

  fp = fopen(filename, "rb");
  if (fp != NULL) {
    fseek(fp, 0, SEEK_END);
    length = ftell(fp);
  }

  if (fp != NULL) {
    fclose(fp);
    fp = NULL;
  }

  return length;
}

/*
写入日志文件
@param filename [in]: 日志文件名
@param max_size [in]: 日志文件大小限制
@param buffer [in]: 日志内容
@param buf_size [in]: 日志内容大小
@return 空
*/
void write_log_file(char* filename, long max_size, char* buffer, unsigned buf_size) {
  if (filename != NULL && buffer != NULL) {
    // 文件超过最大限制, 删除
    long length = get_file_size(filename);

    if (length > max_size) {
      unlink(filename);  // 删除文件
    }

    // 写日志
    {
      FILE* fp;
      fp = fopen(filename, "at+");
      if (fp != NULL) {
        char* now = get_local_time_with_ms();
        fwrite(now, strlen(now), 1, fp);
        fwrite(buffer, buf_size, 1, fp);

        free(now);
        now = NULL;

        fclose(fp);
        fp = NULL;
      }
    }
  }
}

int main(int argc, char** argv) {
  int idx;
  for (idx = 0; idx < 10; ++idx) {
    char buffer[32];
    memset(buffer, 0, sizeof(buffer));
    int chars_written = snprintf(buffer, sizeof(buffer), "====> %d\n", idx);
    if (chars_written > 0 && chars_written < sizeof(buffer)) {
      write_log_file("log.txt", FILE_MAX_SIZE, buffer, chars_written);
#ifdef WIN32
      Sleep(100);  // 毫秒
#else
      usleep(100 * 1000);  // 毫秒
#endif
    } else {
      // Handle snprintf failure
      // Maybe log an error or take appropriate action
    }
  }
  return 0;
}
详细说明与优化
  1. 时间戳获取函数 (get_local_time_with_ms):

    • 使用gettimeofday函数获取当前时间和微秒级精度,并将其格式化为可读的时间字符串,以便于在日志中记录事件发生的时间。
  2. 文件大小获取函数 (get_file_size):

    • 使用文件操作函数fopen, fseekftell来获取日志文件的当前大小,用于后续判断是否需要清空日志文件。
  3. 日志写入函数 (write_log_file):

    • 根据传入的日志内容,将时间戳和实际日志信息写入到指定的日志文件中。如果日志文件超过预设的最大大小限制,将会自动删除旧日志文件。
  4. 跨平台支持:

    • 使用了预处理指令#ifdef WIN32#else,在Windows平台下使用Sleep函数暂停执行,Linux平台下使用usleep函数进行暂停。
测试代码

为了验证日志记录功能的正确性,我们提供了以下测试代码,用于循环写入10条简单的日志信息:

int main(int argc, char** argv) {
  int idx;
  for (idx = 0; idx < 10; ++idx) {
    char buffer[32];
    memset(buffer, 0, sizeof(buffer));
    int chars_written = snprintf(buffer, sizeof(buffer), "====> %d\n", idx);
    if (chars_written > 0 && chars_written < sizeof(buffer)) {
      write_log_file("log.txt", FILE_MAX_SIZE, buffer, chars_written);
#ifdef WIN32
      Sleep(100);  // 毫秒
#else
      usleep(100 * 1000);  // 毫秒
#endif
    } else {
      // Handle snprintf failure
      // Maybe log an error or take appropriate action
    }
  }
  return 0;
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘色的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值