Linux_C++_日志实例

linux系统中c++写日志文件功能分享 主要介绍了linux系统中c++写日志文件功能,简化了glog,只保留了写日志文件的功能,只是改写了linux版本,需要的朋友可以参考下 立即下载

Logger.hpp

// 头文件保护宏:防止头文件被重复包含,是C/C++的常规做法
#ifndef __LOGGER_HPP
#define __LOGGER_HPP

// 标准输入输出流:用于控制台打印
#include <iostream>
// C标准输入输出:用于snprintf等函数
#include <cstdio>
// 字符串处理:日志内容存储和拼接
#include <string>
// 智能指针:管理日志策略对象的生命周期,避免内存泄漏
#include <memory>
// 字符串流:高效拼接日志内容(比直接字符串+=更高效)
#include <sstream>
// 时间相关:基础时间函数
#include <ctime>
// 高精度时间:获取微秒级时间戳,提升日志时间精度
#include <sys/time.h>
// 获取进程ID:syscall相关,getpid()需要
#include <unistd.h>
// 文件系统操作:C++17标准,用于创建日志目录
#include <filesystem> 
// 文件流:用于日志文件的写入
#include <fstream>
// 自定义互斥锁:用于保证日志输出的线程安全(需确保Mutex.hpp实现了线程安全的锁)
#include "Mutex.hpp"

// 日志模块命名空间:封装所有日志相关的类型和函数,避免命名冲突
namespace NS_LOG_MODULE
{
    // 日志等级枚举:定义不同严重程度的日志类型,便于分类和筛选
    enum class LogLevel
    {
        INFO,    // 普通信息:程序正常运行的状态提示
        WARNING, // 警告:非致命问题,需关注但不影响程序运行
        ERROR,   // 错误:功能异常,部分模块可能受影响
        FATAL,   // 致命错误:程序无法继续运行,需立即终止
        DEBUG    // 调试信息:开发阶段用,发布时可关闭
    };

    /**
     * @brief 将日志等级枚举转换为对应的字符串,便于日志输出展示
     * @param level 日志等级枚举值
     * @return 对应等级的字符串(如LogLevel::INFO返回"INFO")
     */
    std::string LogLevel2Message(LogLevel level)
    {
        switch (level)
        {
        case LogLevel::INFO:
            return "INFO";
        case LogLevel::WARNING:
            return "WARNING";
        case LogLevel::ERROR:
            return "ERROR";
        case LogLevel::FATAL:
            return "FATAL";
        case LogLevel::DEBUG:
            return "DEBUG";
        default:
            return "UNKNOWN";// 防御性编程:处理未知等级
        }
    }
    /**
     * @brief 获取当前系统的高精度时间(精确到微秒)
     * @return 格式化后的时间字符串,格式:YYYY-MM-DD HH:MM:SS.微秒
     * @note 使用localtime_r(可重入版本)而非localtime,避免线程安全问题
     */
    std::string GetCurrentTime()
    {
        // 存储秒+微秒的高精度时间结构体
        struct timeval current_time;
        // 获取当前时间(秒+微秒),第二个参数为时区(nullptr表示本地时区)
        int n = gettimeofday(&current_time, nullptr);
        (void)n;

        // 分解时间为年/月/日/时/分/秒的结构体
        struct tm struct_time;
        // localtime_r是线程安全的,将秒数转换为本地时间结构体
        localtime_r(&(current_time.tv_sec), &struct_time); // r: 可重入函数
        // 存储格式化后的时间字符串
        char timestr[128];
        // 格式化时间:年(+1900)、月(+1)、日、时、分、秒、微秒
        snprintf(timestr, sizeof(timestr), "%04d-%02d-%02d %02d:%02d:%02d.%ld",
                 struct_time.tm_year + 1900,  // tm_year是从1900年开始的偏移量
                 struct_time.tm_mon + 1,      // tm_mon范围0-11,需+1
                 struct_time.tm_mday,         // 日(1-31)
                 struct_time.tm_hour,         // 时(0-23)
                 struct_time.tm_min,          // 分(0-59)
                 struct_time.tm_sec,          // 秒(0-59)
                 current_time.tv_usec);       // 微秒(0-999999)
        return timestr;
    }

    // ===================== 日志输出策略模式 =====================
    // 设计思路:策略模式——将"日志输出行为"封装为独立的策略类,
    // 可灵活切换(控制台/文件/按等级分文件),符合开闭原则
    /**
     * @brief 日志输出策略的抽象基类(策略接口)
     * @note 所有具体输出策略(控制台、文件)都需继承此类并实现SyncLog
     */
    class LogStrategy
    {
    public:
        // 虚析构函数:确保子类析构时能正确调用自身的析构函数
        virtual ~LogStrategy() = default;
        /**
         * @brief 同步输出日志的纯虚函数(核心接口)
         * @param message 格式化后的完整日志字符串
         */
        virtual void SyncLog(const std::string &message) = 0;
    };

    /**----------------------------------------------------------------------------
     * @brief 控制台日志输出策略:将日志打印到控制台(stderr)
     * @note 加互斥锁保证多线程下日志不被打乱
     */
    class ConsoleStrategy : public LogStrategy
    {
    public:
        /**
         * @brief 实现控制台日志输出
         * @param message 完整日志字符串
         * @note 使用std::cerr而非std::cout:cerr无缓冲,实时输出;cout有缓冲可能延迟
         */    
        void SyncLog(const std::string &message) override
        {
            // 加锁:保证多线程下控制台输出的日志是完整的(避免不同线程日志混在一起)
            LockGuard lockguard(_mutex);
            std::cerr << message << std::endl; // ??
        }
        ~ConsoleStrategy()
        {
        }

    private:
        Mutex _mutex;// 如果多个线程用的都是一个logger实例的函数,会导致并发问题,所以需要加锁
        //如果多个线程分别用不同的logger实例的函数,那么需要加上 static,变成所有实例共用这一把锁
        //static Mutex _mutex;
        //但是在绝大多数的工程实践中,日志系统确实只需要一个实例(单例模式)就够了。
    };

    // 日志文件默认配置:默认日志目录、默认日志文件名
    const std::string defaultpath = "./log";    // 默认日志存储目录
    const std::string defaultfilename = "log.txt"; // 默认日志文件名

    /**---------------------------------------------------------------------------------
     * @brief 文件日志输出策略:将日志写入指定文件
     * @note 1. 自动创建日志目录 2. 追加模式写入 3. 加锁保证线程安全
     */
    class FileLogStrategy : public LogStrategy
    {
    public:
        /**
         * @brief 构造函数:初始化日志路径和文件名,自动创建日志目录
         * @param path 日志存储目录(默认:./log)
         * @param name 日志文件名(默认:log.txt)
         */
        FileLogStrategy(const std::string &path = defaultpath, const std::string &name = defaultfilename)
            : _logpath(path),
              _logfilename(name)
        {
            // 加锁:保证多线程下目录创建操作的原子性
            LockGuard lockguard(_mutex);
            
            // 如果目录已存在,直接返回;否则创建目录
            if (std::filesystem::exists(_logpath))
                return;
            try
            {
                // 创建目录(包括多级目录,如./log/2024/01)
                std::filesystem::create_directories(_logpath);
            }
            catch (const std::filesystem::filesystem_error &e)
            {
                // 捕获目录创建失败的异常,打印错误信息
                std::cerr << e.what() << '\n';
            }
            /*try-catch 只能捕获代码中**主动抛出(throw)**的错误,
            或者标准库里定义好的错误。
            它捕获不了真正的内存崩溃(Segfault)。*/
        }
        /**
         * @brief 实现文件日志输出
         * @param message 完整日志字符串
         * @note 1. 追加模式打开文件(ios::app) 2. 每次写入后关闭文件(保证数据落盘)
         */
        void SyncLog(const std::string &message) override
        {
            //为锁构建局部作用域{}
            {
                // 加锁:保证多线程下文件写入的原子性(避免文件内容错乱)
                LockGuard lockguard(_mutex);
                // 路径拼接修正:如果目录末尾没有/,补充/(如./log → ./log/)
                if (!_logpath.empty() && _logpath.back() != '/')
                {
                    _logpath += "/";
                }
                // 完整的日志文件路径(如./log/log.txt)
                std::string targetlog = _logpath + _logfilename; 
                // 以追加模式打开文件(ios::app:写入到文件末尾)
                std::ofstream out(targetlog, std::ios::app); 
                // 检查文件是否成功打开
                if (!out.is_open())
                {
                    std::cerr << "open " << targetlog << "failed" << std::endl;
                    return;
                }
                // 写入日志内容(换行分隔)
                out << message << "\n";
                // 关闭文件:确保数据立即落盘(避免缓冲区数据丢失)
                out.close();
            }
        }

        ~FileLogStrategy()
        {
        }
        //~FileLogStrategy() = default;也可这样写

    private:
        std::string _logpath;      // 日志文件存储目录
        std::string _logfilename;  // 日志文件名
        Mutex _mutex;              // 文件写入的互斥锁
    };

    // 交给大家
    // const std::string defaultfilename = "log.info";
    // const std::string defaultfilename = "log.warning";
    // const std::string defaultfilename = "log.fatal";
    // const std::string defaultfilename = "log.error";
    // const std::string defaultfilename = "log.debug";
     // 文件策略&&分日志等级来进行保存
    // class FileLogLevelStrategy : public LogStrategy
    // {
    // public:
    // private:
    // };


    // ===================== 核心日志类 =====================
    /**
     * @brief 日志核心类:负责日志内容的构建和输出策略的管理
     * @note 1. 组合日志输出策略(控制台/文件) 2. 提供RAII风格的日志构建方式
     */
    class Logger
    {
        // 日志的生成:
        // 构建日志字符串
    public:
        /**
         * @brief 默认构造函数:默认使用控制台输出策略
         */
        Logger()
        {
            UseConsoleStrategy();
        }
        /**
         * @brief 切换为控制台输出策略
         * @note 使用std::make_unique创建智能指针,自动管理内存
         */
        void UseConsoleStrategy()
        {
            _strategy = std::make_unique<ConsoleStrategy>();
        }
        /**
         * @brief 切换为文件输出策略
         */        
        void UseFileStrategy()
        {
            _strategy = std::make_unique<FileLogStrategy>();
        }
        /**
         * @brief 日志消息内部类:RAII风格构建日志内容,标识一条完整的日志信息= 做半部分固定部分 + 右半部分不固定部分
         * @note 1. 构造时拼接固定日志头(时间、等级、PID等) 2. 析构时自动输出日志 3. 支持<<流式拼接日志内容
         */
        class LogMessage
        {
        public:
            /**
             * @brief 构造函数:初始化日志固定头信息
             * @param level 日志等级
             * @param filename 日志所在的源文件名(__FILE__宏)
             * @param line 日志所在的行号(__LINE__宏)
             * @param logger 外部Logger对象的引用(用于调用输出策略)
             */
            LogMessage(LogLevel level, std::string &filename, int line, Logger &logger)
                : _level(level),
                  _curr_time(GetCurrentTime()),  // 当前高精度时间
                  _pid(getpid()),                // 当前进程ID
                  _filename(filename),           // 源文件名
                  _line(line),                   // 行号
                  _logger(logger)                // 外部Logger引用
            {
                // 拼接日志固定头:[时间] [等级] [PID] [文件名] [行号] - 
                std::stringstream ss;
                ss << "[" << _curr_time << "] "
                   << "[" << LogLevel2Message(_level) << "] "
                   << "[" << _pid << "] "
                   << "[" << _filename << "] "
                   << "[" << _line << "] "
                   << " - ";
                // 初始化日志内容为固定头
                _loginfo = ss.str();
            }
            /**
             * @brief 重载<<运算符:支持流式拼接日志内容
             * @tparam T 任意可输出的类型(字符串、数字、对象等)
             * @param info 要拼接的日志内容
             * @return 当前LogMessage对象的引用(支持链式调用,如log << "a" << "b")
             */            
            template <typename T>
            LogMessage &operator<<(const T &info)
            {
                std::stringstream ss;
                ss << info;          // 将任意类型转换为字符串
                _loginfo += ss.str();// 拼接到日志内容中
                return *this;        // 返回自身,支持链式调用
            }
            /**
             * @brief 析构函数:自动输出日志(RAII核心)
             * @note 生命周期结束时自动调用策略的SyncLog输出日志,无需手动调用
             */
            ~LogMessage()
            {
                // 检查策略是否有效
                if (_logger._strategy)
                {
                    // 调用策略的输出函数
                    _logger._strategy->SyncLog(_loginfo);
                }
            }

        private:
            LogLevel _level;        // 日志等级
            std::string _curr_time; // 当前时间字符串
            pid_t _pid;             // 进程ID
            std::string _filename;  // 源文件名
            int _line;              // 行号
            std::string _loginfo;   // 完整的日志内容(固定头+自定义内容)

            // 一个引用,引用外部的Logger类对象
            Logger &_logger; // 方便我们后续进行策略式刷新
        };


        /**
         * @brief 重载()运算符:创建LogMessage对象,触发日志构建
         * @param level 日志等级
         * @param filename 源文件名(__FILE__)
         * @param line 行号(__LINE__)
         * @return LogMessage对象(RAII风格,析构时自动输出)
         */
        LogMessage operator()(LogLevel level, std::string filename, int line)
        {
            // 这里已经不是内部类了
            // 故意采用拷贝LogMessage
            return LogMessage(level, filename, line, *this);
        }

        ~Logger()
        {
        }

    private:
        // 日志输出策略的智能指针:自动管理策略对象的生命周期
        std::unique_ptr<LogStrategy> _strategy; // 刷新策略
    };

    // 全局日志对象:整个程序共享,方便直接使用
    Logger logger;

    // 宏定义:快速切换输出策略(简化调用)
    #define ENABLE_CONSOLE_LOG_STRATEGY() logger.UseConsoleStrategy();
    #define ENABLE_FILE_LOG_STRATEGY() logger.UseFileStrategy();

    // 核心宏:简化日志调用(结合__FILE__/__LINE__自动填充文件名和行号)
    // 使用示例:LOG(LogLevel::INFO) << "程序启动成功";
    #define LOG(level) logger(level, __FILE__, __LINE__)

}

#endif // __LOGGER_HPP

__FILE__和__LINE__是 C/C++ 编译器内置的预定义宏(也叫编译器宏)

宏名含义类型
__FILE__被替换为当前源代码文件的路径字符串(如/home/user/project/logger.cpp)字符串常量
__LINE__

被替换为当前代码行的行号整数(比如你写printf("%d", __LINE__);

在第 20 行,就会替换成 20)

整数常量

Mutex.hpp

#pragma once

#include <iostream>
#include <pthread.h>
#include "Logger.hpp"


class Mutex
{
public:
    Mutex()
    {
        pthread_mutex_init(&_lock, nullptr);
    }
    void Lock()
    {
        pthread_mutex_lock(&_lock);
    }
    pthread_mutex_t *Ptr()
    {
        return &_lock;
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_lock);
    }
    ~Mutex()
    {
        pthread_mutex_destroy(&_lock);
    }
private:
    pthread_mutex_t _lock;
};

class LockGuard // RAII风格代码
{
public:
    LockGuard(Mutex &lock):_lockref(lock)
    {
        _lockref.Lock();
    }
    ~LockGuard()
    {
        _lockref.Unlock();
    }
private:
    Mutex &_lockref;
};

Main.cc

#include "Logger.hpp"
#include <thread>
#include <vector>

using namespace NS_LOG_MODULE;

void TestConsoleLog()
{
    std::cout << "========= 测试控制台输出 =========" << std::endl;
    // 默认是 ConsoleStrategy
    ENABLE_CONSOLE_LOG_STRATEGY();
    LOG(LogLevel::INFO) << "这是一条普通信息";
    LOG(LogLevel::WARNING) << "这是一个警告, 错误码: " << 404;
    LOG(LogLevel::DEBUG) << "调试信息: 变量 x = " << 3.14;
    sleep(1); // 暂停一下,方便观察时间戳变化
}

void TestFileLog()
{
    std::cout << "\n========= 测试文件输出 =========" << std::endl;
    
    // 切换到文件策略
    // 这会自动创建 ./log 目录和 log.txt 文件
    ENABLE_FILE_LOG_STRATEGY();
    
    std::cout << "策略已切换为文件,请查看 ./log/log.txt" << std::endl;

    LOG(LogLevel::INFO) << "这条信息应该出现在文件中";
    LOG(LogLevel::ERROR) << "数据库连接失败";
    LOG(LogLevel::FATAL) << "系统即将崩溃!!";
    
    // 模拟批量写入
    for(int i = 0; i < 5; i++) {
        LOG(LogLevel::DEBUG) << "文件日志计数: " << i;
    }
}

// 模拟多线程写日志,测试线程安全
void ThreadTask(int id)
{
    LOG(LogLevel::INFO) << "我是线程 " << id << ", 正在运行...";
}

void TestMultiThread()
{
    std::cout << "\n========= 测试多线程并发写入 =========" << std::endl;
    // 此时策略依然是文件策略
    std::vector<std::thread> threads;
    for(int i = 0; i < 5; i++)
    {
        threads.emplace_back(ThreadTask, i);
    }

    for(auto& t : threads)
    {
        t.join();
    }
    std::cout << "多线程测试完成,请检查日志文件是否有乱序或缺失。" << std::endl;
}

int main()
{
    // 1. 测试屏幕打印
    TestConsoleLog();

    // 2. 测试文件写入
    TestFileLog();

    // 3. 测试多线程并发
    TestMultiThread();

    // 4. 切回控制台(可选,演示灵活性)
    std::cout << "\n========= 切回控制台 =========" << std::endl;
    ENABLE_CONSOLE_LOG_STRATEGY();
    LOG(LogLevel::INFO) << "我又回到了屏幕上";

    return 0;
}

Makefile

CXX = g++
# 定义编译选项
# -Wall:  开启警告
# -g:     生成调试信息
# -MMD:   关键参数!自动生成依赖文件(.d),但在生成的依赖中忽略系统头文件(<iostream>等)
# -MP:    为头文件生成伪目标,防止删除头文件后导致 make 报错
CXXFLAGS = -MMD 
TARGET = main
SRCS = Main.cc

$(TARGET):$(SRCS)
	$(CXX) $(SRCS) -o $(TARGET)

.PHONY:clean
clean:
	rm -rf $(TARGET)

innovus获取mem pin shape box脚本 innovus mem 的pin shae只能通过attitude editor看属性获取其pin shape的box,但是想用脚本处理一定box时,没有别的办法能直接获取box属性。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 阅读详情

相关推荐

CHB-MIT波士顿儿童医院癫痫EEG脑电数据处理(一)

CHB-MIT癫痫EEG脑电数据处理CHB-MIT头皮脑电图数据介绍CHB-MIT头皮脑电图数据下载CHB-MIT头皮脑电图数据处理提取原始数据滤波(0.1~50hz)数据分块(时间窗口) CHB-MIT头皮脑电图数据介绍 该数据库收集自波士顿儿童医院,其中包括患有难治性癫痫发作的儿科患者的脑电图记录。停用抗癫痫药物后最多持续几天对受试者进行监测,以表征其癫痫发作并评估其对手术干预的候选资格。 从22位受试者中收集了23个病例的记录(5例男性,3至22岁; 17例女性,1.5至19岁)。 (案例chb21是

AI_DOG的博客 1万+

【同步&异步可并发日志系统】设计及实现

本项⽬主要实现⼀个⽇志系统,其主要⽀持以下功能:1:可进行日志消息格式的指定 2:可划分出多级别的⽇志消息,并可设置那个级别及以上的日志可以输出 3:可将⽇志写到控制台、⽂件以及按大小切换的滚动⽂件中(一个日志可输出0到多个目的文件) 4:⽀持扩展⽇志写入⽬标地及写入要求 ——— 可拓展性 5:⽀持同步写⽇志和异步写⽇志 6:同步或异步写日志均⽀持多线程程序并发写⽇志 7:拥有全局单列,且设有全局宏函数简化使用难度• CentOS7 • vscode/vim • g++/gdb • Makefile• 类的

ZhuGeBin26的博客 1035

【Allegro学习笔记】常规标贴封装创建-0402封装创建实例

摘要 本文主要介绍如何使用Allegro制作表面贴装封装。 所使用的软件 使用Allegro制作常规贴片封装主要使用的软件有Pad Designer和Allegro 1 0402类封装制作 1.1 0402类封装焊盘分析 0402封装尺寸图如图1...

Honglong 1万+

C++实现Logger日志类

在计算机软件中,日志对记录动作、定位错误起到了至关重要的作用。通常在软件发布后,在用户使用中遇到问题的情况下使用,通过日志定位错误,从而快速解决问题。 而在C++中却没有自己的日志类,想要使用日志通常需要自己定义或者下载使用boost。所以为了方便使用,我简单的实现了日志类的功能。 实现代码如下(Logger.hpp): #pragmaonce #include<iostream> #include<string> #include&...

m0_64428335的博客 1468

Framelet Transform

需要定义 Framelet 的基函数。Framelet 基函数可以是通过组合不同的小波函数生成的。# 这里可以定义 Framelet 基函数,例如一些小波基函数的线性组合# 这是一个示例函数,具体实现需要根据具体的 Framelet 设计# 示例:正弦函数。

qq_33009429的博客 1210

DRAM自测试模块

1 背景技术DDR3/4 SDRAM属于高速外设,最高时钟频率可达到1600MHz,最高速率可达3200MT/s。在存储控制器与DDR34 SDRAM设备之间有一层专为高速接口设计的模拟电路,此电路对于前端设计人员来说,不管在模拟验证阶段和回片测试阶段,都是一个黑盒子。而对于后端测试人员来说若此部分为外购IP,则内部结构也是无法清楚了解的。所以在测试阶段,对于DDR34 SDRAM的测试就具有一定的

Hierro的DDR世界 7011

C++编程:一个简单的日志头文件loghelper.hpp

使用C++构建一个简单的线程安全的日志头文件(head-only)的loghelper.hpp,适用于简单快速的调试程序,又不想引入比较复杂的日志模块。

Where there is life, there is hope. 1240

昇腾,Ascend,NPU,mindie,镜像,部署vllm:第5篇,昇腾环境下部署蒸馏版deepseek-r1,并在dify中注册模型供应商

这两天没少折腾deepseek-r1。之前在A100上用ollama部署了一份DeepSeek-R1-Distill-Qwen-32B,感觉真的特别慢。现在,再用昇腾部署一遍,看看速度能不能更快。p.s. 类似的内容其实已经写了很多遍了。但感觉之前写得都太碎,不够顺畅。接着新模型写篇长文,把能包括的都包括进来。这样大家也不需要到处翻来翻去。

xiezhipu的博客 2450

【Linux C++ 日志系统实战】高性能文件写入 AppendFile 核心方法解析

本文介绍了一个高性能日志系统的核心组件AppendFile,它负责将日志消息高效可靠地写入文件。该组件采用128KB大缓冲区减少IO调用,使用fwrite_unlocked实现无锁写入提升性能,通过循环写入确保数据完整性,并以追加模式保证日志不丢失。同时提供了异常处理、内存管理等功能,支持线程安全操作。文章详细解析了其设计原理、实现细节和使用方法,展示了如何通过缓冲区优化、原子操作等关键技术构建高性能日志写入模块。该组件可直接集成到生产环境,满足高并发、低延迟的日志记录需求。

2401_89207098的博客 520

外部PLC触发VisionMaster多流程运行

上一讲,介绍了海康VisionMaster与西门子PLC1200进行S7通信。在前一讲的基础上,讲解如何通过PLC触发,实现VisionMaster的多流程运行。

haier123888的博客 4651

SPAD IMX479规格_分辨率

当然IMX479具备IMX459几乎全部的数字架构,但也有一个缺点就是贵,这个让头部的主机厂有些犹豫,毕竟大家都在集中火力想把车载LiDAR玩进千元机。如果用一片IMX479是不太可能实现千元内部的,当然国产也在奋起直追,特别在前面的几家SPAD厂商都具备开发IMX479的实力,但相对来说落地可能更是当下所考虑的,IMX479的迭代是基于IMX459,小编已经注意到国内有一两家已经在挑战479的规格了,如果国产SPAD没有大规模量产就直接流片IMX479的规格,可能就有点忽略市场的反馈闭环。

致力于lidar应用开发 2416

linux下c/c++实例之二日志记录及文件读取

Linux下封装一些函数将需要的日志信息打印到控制台或写入文件,并读取文件。

乌托邦 4715

C#与硬件开发入门:从零开始搭建你的第一个硬件项目

《C#硬件开发入门指南》摘要:本文介绍了使用C#进行硬件开发的基础知识,重点讲解了通过串口通信控制硬件设备的实现方法。内容包括:C#硬件开发优势、必备基础知识、环境准备步骤,并提供了一个完整的串口数据读取示例代码。文章还给出了进阶学习建议和常见问题解决方案,帮助开发者快速掌握C#与硬件设备通信的基本技能,为进一步开发物联网、工业控制等应用打下基础。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 972

(自用)共享单车服务器(二) 项目日志

在通常情况下,Linux/UNIX每个程序在开始运行的时刻,都会打开3个已经打开的stream. 分别用来输入,输出,打印诊断和错误信息。例如,%d{%H:%M:%S,%l} 或 %d{%d %m %Y %H:%M:%S,%l}。上文,我们说过日志输出到终端或者文件中实际上是很慢的,会引起IO中断,所以我们可以输出到内存里StringQueueAppender,然后从StringQueueAppender输出到其它地方,这样我们的线程执行是比较高效的。日志级别的意思是低于该级别的日志不会被记录。

weixin_44155149的博客 1219

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

几种常见的项目日志使用方法

在通常情况下,Linux/UNIX每个程序在开始运行的时刻,都会打开3个已经打开的stream. 分别用来输入,输出,打印诊断和错误信息。可以被fprintf、fread等函数使用,他们在程序开始启动后,stdin, stdout, and stderr 的文件描述符是 0, 1和2,其它的文件描述符则排在其后。如果我们实在要用printf或者fprintf去生成日志的话,最好还是加上这些信息,__FILE__ __LINE__ __FUNCTION__, __DATE__, __TIME__。

m0_65635427的博客 1028

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

日志记录c++代码

linux 下日志保存c++代码(已测试可用): log.cpp #include "log.h" #include <iostream> #include <io.h> #include <time.h> #include <sys\stat.h> #include <direct.h> CLog* CLog::m_Instace = NULL; #define SUCCESS 0 int LogMsg(unsigned long uLog

hyg0725的博客 475

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C++ 日志类设计

这篇文章介绍了一个简洁实用的C++日志工具实现方案。核心设计采用单例模式确保全局唯一实例,通过重载operator()实现优雅调用方式如log(INFO,"message")。关键特性包括自动时间戳、多级别日志(INFO/DEBUG/WARNING等)、同时支持控制台和文件输出。实现上仅使用标准库,轻量无依赖,包含可变参数处理、时间格式化和文件写入等实用功能。调用示例展示了不同级别日志的输出效果,格式统一美观。这个日志类代码精简但功能完整,非常适合嵌入各类C++项目中作为基础工具使用,尤

nplplus的博客 1万+

Linux上用C++和GCC开发程序实现两个不同MySQL实例下单个Schema稳定高效的数据迁移到其它MySQL实例

该实现结合了C++的高效性和现代C++的特性,同时利用MySQL X DevAPI提供的高性能接口,能够有效处理大规模数据复制需求。

weixin_30777913的博客 373

WinCE程序C/C++/C#实现带时间标记的日志记录

在程序开发时,为了帮助程序员更好的调试和排错,一般都需要日志记录,这是一个程序员应该养成的良好习惯。本文虽然是在WinCE平台下进行的,但是显然更能够在XP平台上运行,甚至只要对一些文件接口函数进行修改,可以在Linux平台下实现相应功能。     用C/C++编写WinCE程序时,写登录日志的方法。测试开发板:EPCS-6960I    一、C语言编写的带时间标记的日志记录方法 #i

tanghuashijia_的专栏 826

分级别打印日志

#文件log.h 该文件中定义了打印日志的接口。 #ifndef _LOG_H_ #define _LOG_H_ #define INFO_OUTPUT 3 #define WARNING_OUTPUT 2 #define DEBUG_OUTPUT 1 #define ERROR_OUTPUT 0 #define LOG_INFO(args,...)\ do{\ ...

weixin_39446424的博客 695

Linux上用C++和GCC开发程序实现不同MySQL实例下单个Schema之间的稳定高效的数据迁移

【代码】Linux上用C++和GCC开发程序实现MySQL实例下单个Schema之间的稳定高效的数据迁移。

weixin_30777913的博客 484

Linux上用C++和GCC开发程序实现两个不同PostgreSQL实例下单个数据库中多个Schema稳定高效的数据迁移到其它PostgreSQL实例

这个设计在保证功能完整性的同时,充分考虑了大规模数据复制的性能需求,并通过模块化设计保证了可维护性。异常处理和日志系统为生产环境运行提供了必要保障。根据需求,我设计了以下解决方案。

weixin_30777913的博客 677

华为系统服务器开源,开源云服务器系统

开源云服务器系统 内容精选换一换简要介绍log4cpp是一个开源的C++类库,它提供了在C++程序中使用日志和跟踪调试的功能。使用log4cpp,可以很便利地将日志或者跟踪调试信息写入字符流、内存字符串队列、文件、回滚文件、调试器、Windows日志、本地syslog和远程syslog服务器中。语言:C++一句话描述:使用日志和跟踪调试的开源库开源协议:LGPL建议的版简要介绍catj是一个可以将...

weixin_29481259的博客 524

Linux上用C++和GCC开发程序实现不同PostgreSQL实例下单个数据库的多个Schema之间的稳定高效的数据迁移

实际部署时可以根据具体需求调整批量大小、线程数量、重试策略等参数,并通过监控日志文件来观察复制状态和性能指标。

weixin_30777913的博客 549

Linux C++使用动态连接库,静态库的理解

LInux下理解C++编译使用动态连接库,静态库,为了更好的理解作为例子说明,以glog日志库为例说明:// 下面是文件test.cpp,调用glog库打印日志的例子#include <glog/logging.h> int main ( int argc , char *c[] ) { FLAGS_log_dir = "." ; // 将生成的日志文件输出到当前执行程序

dxzysk的专栏 4245

DHCP 服务 LINUX版本

简单实现了DHCP服务,内容涉及到 UDP 广播、封装锁、stl封装队列、日志类、所有代码均使用c++ 、STL 实现、和必要的Linux API 接口。

344
上一篇: C++ 线程实战案例解析
下一篇: C++ 智能指针_详细解释
Howrun777
博客等级 码龄1年 133粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值