美文网首页
C++输出上位机指令到本地txt文件

C++输出上位机指令到本地txt文件

作者: AC编程 | 来源:发表于2024-08-04 14:32 被阅读0次

一、需求描述

在当前运行软件目录下,生成logs目录,输出上位机下发和接收的指令信息,按当前日期生成目录,再按小时生成日志文件,日志文件完整路径示例:D:\MC\MicroCtrl_G\x64\Release\logs\2024-08-05\11.txt

日志内容如下:

13:55:11.833   PUMP    WRITE   3F 56 38 38 33 0D 00 
13:55:11.985   PUMP    READ   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
13:55:12.702   PLATF   WRITE   FE FE 31 01 01 01 01 16 
13:55:12.703   PLATF   WRITE   FE FE 31 01 01 01 01 16 

二、C++ MFC版本

2.1 CLaserCtrl.h文件
#include <vector>
#include <fstream>
#include <afx.h>
#include <afxwin.h>
#include <iostream>
#include <iomanip> // 添加此头文件以使用 setfill 和 setw 函数
#include <string>

class __declspec(dllexport) CLaserCtrl
{

protected:
    /************************************************************************
    功能: 指令日志记录
    输入: lpCmd:指令,如:{0x81, 0x31, 0x31,0x0D}
            len:指令长度,如:4
            sendReceiveType:1=下发指令;2=接收指令
            isTimerCmd:是否为定时执行指令
    ************************************************************************/
    void OutputCmdToFile(LPCSTR lpCmd, int len,int sendReceiveType,bool isTimerCmd);

    bool IsTimerSendCmd(LPCSTR lpCmd, int len);

    bool IsTimerReadCmd(LPCSTR lpCmd, int len);

    // 创建日志目录,如:D:\MC\MicroCtrl_G\x64\Release\logs
    CString CreateLogFolder();

    // 创建目录
    void CreateDirectory(LPCTSTR lpPath);

    // 获取当前项目运行目录,如:D:\MC\MicroCtrl_G\x64\Release
    CString pubGetCurrentDirectory();
}
2.2 CLaserCtrl.cpp文件
void CLaserCtrl::OutputCmdToFile(LPCSTR lpCmd, int len,int sendReceiveType,bool isTimerCmd) {
    SYSTEMTIME st;
    GetLocalTime(&st);

    CStringA timeStr;
    timeStr.Format("%02d", st.wHour);
    CStringA timeFile(timeStr);

    CString timerTag;
    if(isTimerCmd)
    {
        timerTag= "_Timer";
    }

    CString filePath = CreateLogFolder() + "\\"+CString(timeFile)+ timerTag +".txt";
    std::ofstream outFile(filePath,std::ios::app); 

    CStringA strTime;
    strTime.Format("%02d:%02d:%02d.%03d", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    CStringA timeContent(strTime);
    outFile  << timeContent;

    outFile  <<"   LASER";

    if(sendReceiveType ==1)
    {
        outFile  <<"   WRITE   ";
    }else
    {
        outFile  <<"   READ   ";
    }
    
    for (int i = 0; i < len; ++i) {
        // 将十进制转换为十六进制并输出,不足两位用 0 填充
        outFile << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << (int)(unsigned char)lpCmd[i] << " ";
    }

    outFile << "\n";
    outFile.close();
}

bool CLaserCtrl::IsTimerSendCmd(LPCSTR lpCmd, int len)
{
    //23 21 40 55 56 32 46 0D 00
    if (len == 9 && lpCmd[0] == 0x23 && lpCmd[1] == 0x21 && lpCmd[2] == 0x40 && lpCmd[3] == 0x55 && lpCmd[4] == 0x56 && lpCmd[5] == 0x32 && lpCmd[6] == 0x46 && lpCmd[7] == 0x0D && lpCmd[8] == 0x00) {
       return true;
    }

    return false;
}

bool CLaserCtrl::IsTimerReadCmd(LPCSTR lpCmd, int len)
{
    //3C 40 21 55
    if (len > 4 && lpCmd[0] == 0x3C && lpCmd[1] == 0x40 && lpCmd[2] == 0x21 && lpCmd[3] == 0x55) {
       return true;
    }

    return false;
}

CString CLaserCtrl::CreateLogFolder()
{
    SYSTEMTIME st;
    GetLocalTime(&st);

    CStringA dayStr;
    dayStr.Format("%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
    CStringA dayFolder(dayStr);

    CString str = pubGetCurrentDirectory();
    CString strFolder = pubGetCurrentDirectory()+_T("\\logs\\") + CString(dayFolder);
    if (!PathFileExists(strFolder)) CreateDirectory(strFolder);
    return strFolder;
}

CString CLaserCtrl::pubGetCurrentDirectory()
{
    TCHAR pcDirectory[255];
    GetModuleFileName(NULL , pcDirectory , 255);
    CString strDirectory = pcDirectory;
    strDirectory = strDirectory.Left(strDirectory.ReverseFind(_T('\\')));

    return strDirectory;
}

void CLaserCtrl::CreateDirectory(LPCTSTR lpPath)
{
    CString strPath(lpPath) , strPathTem;

    std::vector<int> vnIndex;

    for(int i=0; i<strPath.GetLength(); i++)
    {
        if(strPath[i] == _T('\\'))
        {
            vnIndex.push_back(i);
        }
    }

    for(int i=0; i<vnIndex.size(); i++)
    {
        if(i == vnIndex.size() - 1)
        {
            strPathTem = strPath;
        }
        else
        {
            strPathTem = strPath.Left(vnIndex[i+1]);
        }       

        if(!PathFileExists(strPathTem))
        {
            ::CreateDirectory(strPathTem , NULL);
        }
    }
}

三、C++版本

3.1 PlatformCtrlAPI.h
#include <fstream>
#include <iostream>
#include <iomanip> // 添加此头文件以使用 setfill 和 setw 函数
#include <string>

#include <ctime>
#include <sstream>

/************************************************************************
功能: 指令日志记录
输入: lpCmd:指令,如:{0x81, 0x31, 0x31,0x0D}
        len:指令长度,如:4
        sendReceiveType:1=下发指令;2=接收指令
        isTimerCmd:是否为定时执行指令
************************************************************************/
void OutputCmdToFile(char lpCmd[],int len,int sendReceiveType,bool isTimerCmd);

// 创建日志目录,如:D:\MC\MicroCtrl_G\x64\Release\logs
std::string CreateLogFolder();

// 创建目录
void CreateDirectory(std::string& lpPath);

// 获取当前项目运行目录,如:D:\MC\MicroCtrl_G\x64\Release
std::string PubGetCurrentDic();

// 判断当前目录是否存在
bool DirectoryExists(const std::string& path);
3.2 PlatformCtrlAPI.cpp
void OutputCmdToFile(char lpCmd[],int len,int sendReceiveType,bool isTimerCmd) {
    std::string timerTag;
    if(isTimerCmd)
    {
        timerTag= "_Timer";
    }

    // 获取当前系统时间
    time_t now = time(0);
    struct tm* localNow;
    localNow = localtime(&now);

    // 获取小时
    char timeString[80];
    strftime(timeString, sizeof(timeString), "%H", localNow);

    // 构建文件夹路径
    std::string timeStr = std::string(timeString);
    std::string filePath = CreateLogFolder() + "\\"+timeStr+ timerTag +".txt";
    std::ofstream outFile(filePath,std::ios::app); 

    //日志时间(到毫秒)
    
    std::time_t nowTime = std::time(nullptr);
    struct std::tm* localNowTime = std::localtime(&nowTime);

    std::stringstream ss;
    ss << std::setw(2) << std::setfill('0') << localNowTime->tm_hour << ":" 
       << std::setw(2) << std::setfill('0') << localNowTime->tm_min << ":" 
       << std::setw(2) << std::setfill('0') << localNowTime->tm_sec << "." 
       << std::clock() % 1000;
    outFile  <<ss.str();
    
    outFile  <<"   PLATF";
    if(sendReceiveType ==1)
    {
        outFile  <<"   WRITE   ";
    }else
    {
        outFile  <<"   READ   ";
    }

    for (int i = 0; i < len; ++i) {
        // 将十进制转换为十六进制并输出,不足两位用 0 填充
        outFile << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << (int)(unsigned char)lpCmd[i] << " ";
    }
    outFile << "\n";
    outFile.close();
}

std::string CreateLogFolder()
{
    // 获取当前系统时间
    time_t now = time(0);
    struct tm* localNow;
    localNow = localtime(&now);

    // 格式化时间字符串
    char timeString[80];
    strftime(timeString, sizeof(timeString), "%Y-%m-%d", localNow);

    // 构建文件夹路径
    std::string dayStr = std::string(timeString);
    std::string str = PubGetCurrentDic();
    std::string strFolder = PubGetCurrentDic()+"\\logs\\" + dayStr;

    CreateDirectory(strFolder);
    return strFolder;
}

void CreateDirectory(std::string& lpPath)
{
    bool logDicExists = DirectoryExists(lpPath);
    if(logDicExists == false)
    {
        // 创建文件夹
        if (CreateDirectory(lpPath.c_str(), NULL)) {
            //成功
        } else {
            //失败
        }
    }
}

std::string PubGetCurrentDic()
{
    TCHAR pcDirectory[255];
    GetModuleFileName(NULL , pcDirectory , 255);

    std::string strDirectory = pcDirectory;
    size_t pos = strDirectory.rfind('\\');
    if (pos!= std::string::npos) {
        strDirectory = strDirectory.substr(0, pos);
    }
    return strDirectory;
}

bool DirectoryExists(const std::string& path) {
    DWORD fileAttributes = GetFileAttributes(path.c_str());
    if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
        return false;
    }
    return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY)!= 0;
}

相关文章

网友评论

      本文标题:C++输出上位机指令到本地txt文件

      本文链接:https://www.haomeiwen.com/subject/jzptkjtx.html