跨平台配置文件类TConfig

本文介绍了一个跨平台配置文件类TConfig,提供文件读写功能。通过示例展示了如何设置与获取配置项,并讨论了缓冲区大小的重要性。

这是一个跨平台的配置文件类,它提供了两个接口函数:
int ReadString  (char* sec, char* key, char* value);
int WriteString (char* sec, char* key, char* value);
用来对文件进行操作。

使用示例(Usage example):
TConfig config("desk.ini");
config.WriteString("network", "ip", "192.168.0.1");
char ip[256];
config.ReadString("network", "ip", ip);

使用注意事项:
调用ReadString时,需要保证第3个参数所分配的空间大于文件中该值的空间,
否则会出现缓冲区溢出,我没有解决掉这个问题,欢迎高手告诉我解决之道。
当然,将这个参数的空间设为256字节(宏LINE_SIZE)是不会出错的。

如果在试用这个类的过程中,出现什么问题,或者你有什么好的想法,欢迎
和我联系或在这里留言,非常感谢。zwj123@163.com

/* TConfig.h */
#if !defined _TCONFIG_H_
#define _TCONFIG_H_

#include <stdio.h>

#define MAX_NODE 32
#define LINE_SIZE 256
#define NULL 0

struct key_node;
struct section_node
{
 char *sectionname;
 struct key_node* child;
};

struct key_node
{
 char *keyname;
 char *keyvalue;
 struct section_node* parent;
 struct key_node* next;
};

class TConfig 
{
public:
 TConfig(char*);
 virtual ~TConfig();

 int ReadString  (char* sec, char* key, char* value);
 int WriteString (char* sec, char* key, char* value);

private:
 section_node section[MAX_NODE];
 char *filename;
 bool dirty; //dirty mark

 void initnode();
 void removeblank(char *sz, int flag);
 int  readline(FILE *file, char *linebuf, int offset);
 void UpdateFile();
};

#endif

/* TConfig.cpp */
#include <string.h>
#include <stdlib.h>
#include "TConfig.h"

TConfig::TConfig(char* _filename)
{
 dirty = false;

 filename = new char[strlen(_filename) +1];
 strcpy(filename, _filename);

 for(int i=0; i<MAX_NODE; ++i)
 {
  section[i].sectionname = NULL;
  section[i].child = NULL;
 }

 initnode();
}

TConfig::~TConfig()
{
 if(dirty)
  UpdateFile();
 dirty = false;

 delete filename;

 for(int idx=0; idx<MAX_NODE; ++idx)
 {
  if(section[idx].sectionname == NULL)
   break;

  key_node *p, *pre = section[idx].child;
  while(pre && pre->next)
  {
   p = pre->next;
   if(p){
    pre->next = p->next;
    delete p;
   }
   else
    pre->next = NULL;
  }

  delete section[idx].sectionname; 
 }
}

void TConfig::initnode()
{
 FILE *file;
 char linebuf[LINE_SIZE];
 int index = -1;
 bool bsection = true; //section operation or key operation?
 bool bread = true; //whether or read line?
 int offset = 0;
 struct key_node *p, *prior;
 char *pdest;

 file = fopen(filename, "r+b");
 if(!file)return;

 do
 {
  if(bread)
  {
   fseek(file, offset, SEEK_SET);
   offset = readline(file, linebuf, offset);
   removeblank(linebuf, 0);
  }
  
  bread = true;
  if(bsection)//find section
  {
   if(linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']')//new section
   { 
    index++;
    if(index >= MAX_NODE)break;//the number of section must less than MAX_NODE
    int len = strlen(linebuf) - 2; //don't count '['and ']'
    section[index].sectionname = new char[len+1];
    memcpy(section[index].sectionname, &linebuf[1], len);
    section[index].sectionname[len] = '/0';
    section[index].child = NULL;
    bsection = false; //end finding section
   }
   else
    continue;//continue to find section
  }
  else
  { 
   if(linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']')//new section?
   {
    bread = false;//don't to read new line
    bsection = true;
    continue;
   }
   pdest = strchr(linebuf, '=');
   if(pdest)
   {
    p = new key_node;

    int pos = pdest - linebuf;
    removeblank(pdest+1, 0);//filter '='
    p->keyvalue = new char[strlen(pdest+1)];
    strcpy(p->keyvalue, pdest+1);

    linebuf[pos] = '/0';
    removeblank(linebuf, 0);
    p->keyname = new char[strlen(linebuf)+1];
    strcpy(p->keyname, linebuf);
    
    p->parent = &section[index];
    p->next = NULL;

    //insert key node
    if(section[index].child == NULL)
     section[index].child = p;
    else
    {
     prior = section[index].child;
     while(prior->next)
     {
      prior = prior->next;
     }
     prior->next = p;
    }
   }
  }
 }while(offset != -1 || !bread);//file havn't end or must to handle data

 if(file)fclose(file);
}

/******************************************
* read one line from file in binary mode
* from offset to '/n '
* return vlaue:
* -1:     file end
* others: new offset
******************************************/
int TConfig::readline(FILE *file, char *linebuf, int offset)
{
 int idx=0;
 char ch;

 linebuf[0] = '/0';

 for(;;)
 {
  if(feof(file))break;
  ch = getc(file);
  offset++;
  if(ch == '/n')
  {
   linebuf[idx - 1] = '/0';//remove '/r'
   return offset;
  }
  linebuf[idx++] = ch;
 }

 linebuf[idx-1] = '/0';//filter 'EOF' mark
  return -1;
}

/*********************************
* remove blank  or tab of string
* flag = -1,0,1 : left,both,right
* note: sz length must be less 256
*********************************/
void TConfig::removeblank(char *sz, int flag)
{
 int idx = 0;
 if(strlen(sz) >= LINE_SIZE)return;

 if(flag != 1)
 {
  char buf[256];
  while(sz[idx] == ' ' || sz[idx] == ' ')idx++;
  strcpy(buf, &sz[idx]);
  strcpy(sz, buf);
 }
 if(flag != -1)
 {
  idx = strlen(sz) - 1;
  while(sz[idx] == ' ' || sz[idx] == ' ')idx--;
  sz[idx+1] = '/0';
 }
}

/*********************************************
* return value
* 0 : success
* -1: section cannot find
* -2: key cannot find
*********************************************/
int TConfig::ReadString(char* sec, char* key, char* value)
{
 //find section
 int i=0;
 for(; i<MAX_NODE; ++i)
  if(section[i].sectionname ==NULL || strcmp(section[i].sectionname, sec) == 0)
   break;
 
 if(section[i].sectionname ==NULL)
  return -1;

 key_node* p = section[i].child;
 while(p)
 {
  if(strcmp(p->keyname, key) == 0)//find keyname
  {
   strcpy(value, p->keyvalue); //copy keyvalue to value
   return 0;
  }
  p = p->next;
 }

 return -2;
}

/*********************************************
* return value
* 0 : success
* -1: too much section
*********************************************/
int TConfig::WriteString(char* sec, char* key, char* value)
{
 //find section
 int idx=0;
 for(; idx<MAX_NODE; ++idx)
  if(section[idx].sectionname == NULL || strcmp(section[idx].sectionname, sec) == 0)
   break;
 if(idx >= MAX_NODE)return -1;
 if(section[idx].sectionname == NULL)//new section
 {
  section[idx].sectionname = new char[strlen(sec)+1];
  strcpy(section[idx].sectionname, sec);
 }

 key_node *p = new key_node;
 p->keyname = key;
 p->keyvalue = value;
 p->next = NULL;
 p->parent = &section[idx];

 if(section[idx].child == NULL)
 {
  section[idx].child = p;
  dirty = true;
 }
 else
 {
  key_node *pre = section[idx].child;
  while(pre->next)
  {
   if(strcmp(pre->keyname, p->keyname) ==0)
    break;
   pre = pre->next;
  }
  if(strcmp(pre->keyname, p->keyname) == 0) //old key
  {
   if(strcmp(pre->keyvalue, p->keyvalue) !=0) //key equal but vale not equal
   {
    pre->keyvalue = p->keyvalue;
    dirty = true;
   }
  }
  else //new key
  {
   pre->next = p;
   dirty = true;
  }
 }

 if(dirty)UpdateFile();
 dirty = false;
 return 0;
}

/*************************************
* write list data into file
*************************************/
void TConfig::UpdateFile()
{
 FILE *file = fopen(filename, "w+b");
 if(!file)return;
 
 char linebuf[LINE_SIZE];
 int len;
 
 for(int idx=0; idx<MAX_NODE; ++idx)
 {
  if(section[idx].sectionname == NULL)
   break;

  //write section
  linebuf[0] = '[';
  len = strlen(section[idx].sectionname);
  memcpy(&linebuf[1], section[idx].sectionname, len);
  linebuf[len+1] = ']';
  linebuf[len+2] = '/r';
  linebuf[len+3] = '/n';
  fwrite(linebuf, len+4, 1, file);

  key_node *p = section[idx].child;
  while(p)
  {
   //write key
   len = strlen(p->keyname);
   strcpy(linebuf, p->keyname);
   linebuf[len] = '=';
   memcpy(&linebuf[len+1], p->keyvalue, strlen(p->keyvalue));
   len = len + 1 + strlen(p->keyvalue);
   linebuf[len] = '/r';
   linebuf[len+1] = '/n';
   fwrite(linebuf, len+2, 1, file);

   p=p->next;
  }

  //write blank line
  linebuf[0] = '/r';
  linebuf[1] = '/n';
  fwrite(linebuf, 2, 1, file);
 }

 if(file)fclose(file);
}

1. Vision.Data.Models.dll - 数据模型和接口 text Vision.Data.Models.dll/ ├── Models/ # 数据模型 │ ├── InspectionResult.cs # 检测结果模型 │ ├── CameraInfo.cs # 相机信息模型 │ ├── Recipe.cs # 检测配方模型 │ ├── SystemConfig.cs # 系统配置模型 │ ├── AlgorithmResult.cs # 算法结果模型 │ ├── DeviceStatus.cs # 设备状态模型 │ └── LogEntry.cs # 日志条目模型 │ ├── Interfaces/ # 接口定义 │ ├── IVisionAlgorithm.cs # 算法通用接口 │ ├── ILogger.cs # ✅ 日志接口 │ ├── IConfigurable.cs # 可配置接口 │ ├── IInitializable.cs # 可初始化接口 │ └── IDisposableResource.cs # 资源释放接口 │ ├── Enums/ # 枚举定义 │ ├── DeviceType.cs # 设备型枚举 │ ├── InspectionStatus.cs # 检测状态枚举 │ ├── ErrorCodes.cs # 错误代码枚举 │ ├── TriggerMode.cs # 触发模式枚举 │ └── LogLevel.cs # ✅ 日志级别枚举 │ └── Events/ # 事件参数 ├── ImageGrabbedEventArgs.cs # 图像采集事件 ├── InspectionCompletedEventArgs.cs # 检测完成事件 └── DeviceStatusChangedEventArgs.cs # 设备状态变化事件 2. Vision.Device.Interfaces.dll - 设备驱动接口 text Vision.Device.Interfaces.dll/ ├── Camera/ # 相机接口 │ ├── ICamera.cs # 相机主接口 │ ├── ICameraInfo.cs # 相机信息接口 │ └── ICameraAsync.cs # 相机异步接口 │ ├── Light/ # 光源接口 │ ├── ILightController.cs # 光源控制器接口 │ └── ISerialLight.cs # 串口光源接口 │ ├── IO/ # IO接口 │ ├── IIOController.cs # IO控制器接口 │ └── ICommunication.cs # 通信接口 │ ├── Common/ # 通用设备接口 │ ├── IDevice.cs # 设备基础接口 │ ├── IConnectable.cs # 可连接接口 │ ├── IConfigurableDevice.cs # 可配置设备接口 │ └── IDeviceStatus.cs # 设备状态接口 │ └── Exceptions/ # 异常 ├── DeviceException.cs # 设备异常基 ├── CameraException.cs # 相机异常 └── ConnectionException.cs # 连接异常 3. Vision.Core.dll - 核心引擎(包含日志实现) text Vision.Core.dll/ ├── Engine/ # 引擎核心 │ ├── VisionEngine.cs # 视觉引擎主 │ ├── DeviceManager.cs # 设备管理器 │ └── AlgorithmExecutor.cs # 算法执行器 │ ├── Services/ # 核心服务 │ ├── ConfigManager.cs # 配置管理服务 │ ├── RecipeManager.cs # 配方管理服务 │ ├── InspectionService.cs # 检测流程服务 │ └── DataService.cs # 数据服务 │ ├── Utilities/ # 工具(✅包含日志实现) │ ├── Logger.cs # ✅ 日志系统实现 │ ├── FileLogWriter.cs # ✅ 文件日志写入器 │ ├── ConsoleLogWriter.cs # ✅ 控制台日志写入器 │ ├── PluginLoader.cs # 插件加载器 │ ├── ImageHelper.cs # 图像工具 │ └── ExtensionMethods.cs # 扩展方法 │ └── Events/ # 事件处理 ├── VisionEventArgs.cs # 事件参数基 ├── DeviceEventArgs.cs # 设备事件参数 └── InspectionEventArgs.cs # 检测事件参数 4. 设备驱动DLL结构 Vision.Device.Camera.Hik.dll - 海康相机 text Vision.Device.Camera.Hik.dll/ ├── HikCamera.cs # 海康相机实现 ├── HikCameraInfo.cs # 海康相机信息 ├── HikSDKWrapper.cs # 海康SDK封装 └── HikConstants.cs # 海康常量定义 Vision.Device.Camera.HalconGeneric.dll - Halcon通用相机 text Vision.Device.Camera.HalconGeneric.dll/ ├── HalconGenericCamera.cs # Halcon通用相机实现 ├── HalconAcquisition.cs # Halcon采集封装 ├── CameraDiscoverer.cs # 相机发现 └── HalconConversion.cs # Halcon转换工具 Vision.Device.Light.Serial.dll - 串口光源 text Vision.Device.Light.Serial.dll/ ├── SerialLightController.cs # 串口光源控制器 ├── LightProtocol.cs # 光源通信协议 ├── CommandBuilder.cs # 命令构建器 └── SerialPortManager.cs # 串口管理 5. 算法模块DLL结构 Vision.Algorithms.Base.dll - 基础算法 text Vision.Algorithms.Base.dll/ ├── BasicAlgorithms.cs # 基础算法主 ├── ImageProcessing/ # 图像处理算法 │ ├── ThresholdAlgorithm.cs # 二值化算法 │ ├── FilterAlgorithm.cs # 滤波算法 │ └── MorphologyAlgorithm.cs # 形态学算法 │ ├── Measurement/ # 测量算法 │ ├── EdgeDetection.cs # 边缘检测 │ ├── CaliperTool.cs # 卡尺工具 │ └── CircleFitting.cs # 圆拟合 │ ├── Recognition/ # 识别算法 │ ├── BarcodeReader.cs # 条码识别 │ ├── QRCodeReader.cs # 二维码识别 │ └── OCRBasic.cs # 基础OCR │ └── Analysis/ # 分析算法 ├── BlobAnalyzer.cs # 斑点分析 ├── ColorAnalysis.cs # 颜色分析 └── StatisticalAnalysis.cs # 统计分析 Vision.Algorithms.Advanced.dll - 高级算法接口 text Vision.Algorithms.Advanced.dll/ ├── Interfaces/ # 高级算法接口 │ ├── IAdvancedAlgorithm.cs # 高级算法接口 │ ├── ITrainableAlgorithm.cs # 可训练算法接口 │ └── IModelBasedAlgorithm.cs # 基于模型的算法接口 │ ├── Models/ # 算法模型 │ ├── AlgorithmParameters.cs # 算法参数模型 │ ├── TrainingData.cs # 训练数据模型 │ └── ModelInfo.cs # 模型信息 │ ├── Management/ # 算法管理 │ ├── AlgorithmExecutor.cs # 算法执行器 │ ├── PluginManager.cs # 插件管理器 │ └── ModelManager.cs # 模型管理器 │ └── Utilities/ # 算法工具 ├── AlgorithmHelper.cs # 算法工具 ├── ValidationHelper.cs # 验证工具 └── PerformanceMonitor.cs # 性能监控 这样看呢
最新发布
11-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值