CAPL 脚本对.ini 配置文件的高阶操作

Posted 蚂蚁小兵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAPL 脚本对.ini 配置文件的高阶操作相关的知识,希望对你有一定的参考价值。

📙 相关文章


📘前言

  • 🍅前面其实我们已经掌握了对配置文件,文本文件的读写函数和方法,如果一个INI文件只有少许的键值对,那么用内置函数也还凑合,但是当INI文件中的键值对多了起来,内置函数一个一个去读写的方式就非常繁琐,本节就针对这种情况对INI文件的读写方式进行升级,以达到快速便捷读写多键值对的情况
  • 🍅演示软硬件环境 Win10 x64 ; CANoe 11 SP2 x64

目录

📗 批量读取代码讲解

  • 1️⃣ 本节演示仍然基于 bmw2.cfg ,新增一个Nework Node ,用于按键触发测试


  • 2️⃣ 下图的test.ini 文件是我们的测试文件,键值对有很多


  • 3️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin文件中
  • IniAuto.can中代码:
/*@!Encoding:936*/
includes

  #include "IniAuto.cin"


on key 'u'

  write("*****press u***********");
  getKeyValueFromINI(Ini_data_path,var_Ini_Data); 
  if(1) //debug check values
  
    int i ;
    write ("************************Debug data******************************");
    for(i = 0 ;i < var_Ini_Data.items ;i++)
    
      write ("*******section:%s*******",var_Ini_Data.section[i]);
      write ("*******index:%d***keys:%s*******",i,var_Ini_Data.keys[i]);
      write ("*******index:%d***values:%s*******",i,var_Ini_Data.values[i]);
       
   



  • 4️⃣ 头文件 IniAuto.cin中代码:
/*@!Encoding:936*/

variables
  
    char Ini_data_path[100] = ".//TestModule//IniAutoCode//test.ini";  
    char Ini_data_path_out[100] = ".//TestModule//IniAutoCode//test_out.ini";  
    const int max_items = 200 ;
    const int max_keys_size = 50 ;
    const int max_values_size = 300 ;
  
    struct Ini_Data // record Ini data
  
    int  items;
    char section[max_items][max_keys_size];
    char keys   [max_items][max_keys_size];
    char values [max_items][max_values_size];
 
  ;
   struct Ini_Data var_Ini_Data;


/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
批量读INI
----------------------------------------------------------------------------------------------------
***************************************************************************************************/
int getKeyValueFromINI(char FilePath[], struct Ini_Data Temp_var_Ini_Data)
 
  int i,j,glbHandle;
  char buffer[max_values_size];
  long section_find, key_find;
  char section_temp[max_keys_size];
  char keys_temp_1[max_keys_size]    ,keys_temp_2[max_keys_size];
  char values_temp_1[max_values_size],values_temp_2[max_values_size];
  
  glbHandle = OpenFileRead (FilePath,0);
  
  if (glbHandle!=0 )
     
    write("Open file :%s passed.",FilePath);
    j = 0;
    
    while(fileGetStringSZ(buffer,elcount(buffer),glbHandle)!=0)   
         
      section_find = strstr_regex(buffer, "\\\\[.*?\\\\]"); //用正则表达式匹配 []
      if(section_find != -1)
       
        ClearCharArray(section_temp);
        substr_cpy (section_temp,buffer,1,strlen(buffer)-2,  elcount(buffer));//掐头去尾,去掉[]
        continue ; 
       
      
      key_find = strstr(buffer, "=");     
      
      if(key_find != -1)
      
        ClearCharArray(keys_temp_1);ClearCharArray(keys_temp_2); //临时字符串使用之前要初始化
        substr_cpy (keys_temp_1,buffer,0,key_find,  elcount(buffer));// = 前的key
        remove_space(keys_temp_1,keys_temp_2);                 //清除字符传中的空格
       
        ClearCharArray(values_temp_1);ClearCharArray(values_temp_2); 
        substr_cpy (values_temp_1,buffer,key_find+1,strlen(buffer) - key_find, elcount(buffer));//= 后的value
        remove_space(values_temp_1,values_temp_2);

        strncpy (Temp_var_Ini_Data.section[j],section_temp  ,elcount(Temp_var_Ini_Data.section[j]));
        strncpy (Temp_var_Ini_Data.keys[j]   ,keys_temp_2   ,elcount(Temp_var_Ini_Data.keys[j]));
        strncpy (Temp_var_Ini_Data.values[j] ,values_temp_2 ,elcount(Temp_var_Ini_Data.values[j]));
        j++;  // index ++   
                 
      
    Temp_var_Ini_Data.items = j ;  // 最后统计多少行数据
    fileClose (glbHandle);  
    
  else
  
    write("Read file :%s failed.",FilePath);
    return 0; //failed    
  
  return 1; //passed


/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
去除字符串的空格
----------------------------------------------------------------------------------------------------
***************************************************************************************************/
void remove_space(char input_c[],char out_c[]) 

  
  int i,j ;
  j=0;
  
  for(i = 0; i< strlen(input_c);i++)
  
    if (input_c[i] != ' ')
    
      out_c[j] = input_c[i];
      j++;
    
   

/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
字符串初始化
----------------------------------------------------------------------------------------------------
***************************************************************************************************/
void ClearCharArray(char arrIn[])

	int i, length;
  length = strlen(arrIn);
  for(i=length;i>=0;i--)
   arrIn[i]=0x00; 
  



  • 5️⃣ 头文件 IniAuto.cin中不良定义解释
    说明:因为涉及到批量操作,所有都化整为零,全部key/value的数据类型都视为字符串操作,实际代码中,如果有整形浮点型的,请再进行格式转换


  • 6️⃣ 头文件 IniAuto.cingetKeyValueFromINI 函数的注释


  • 7️⃣ 按键’u‘,看下测试结果:

  • 我们已经把ini的键值对都转换为了CAPl的数组类型,那么这样我们在下一步无论怎么去批量读,改写,删除

📗 批量写入代码讲解

  • 1️⃣ 我们读取了之后,可能的操作是改写,删除,添加,甚至是新建操作,那么这一系列操作之后,我们还要保存到原来的INI文件的。

  • 2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin文件中

  • IniAuto.can中的增加的代码:

/*@!Encoding:936*/
on key 'm'

  write("*****press m***********");
  
  SetKeyValueToINI(Ini_data_path_out,var_Ini_Data);


  • 3️⃣ 头文件 IniAuto.cin中增加的代码:
/*@!Encoding:936*/

/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
批量写入Key/value 到INI
----------------------------------------------------------------------------------------------------
***************************************************************************************************/
int SetKeyValueToINI(char FilePath[], struct Ini_Data Temp_var_Ini_Data)
 
  long retVal;
  int i,j,glbHandle;
  char buffer[max_values_size];
  char section_temp[max_items][max_keys_size];
  char tempText[max_values_size];

  
  ClearCharArray(section_temp);
  glbHandle = OpenFileWrite(FilePath,0); // 写入文件,以覆盖源文件的形式
  
  if (glbHandle!=0 )
     
    write("Open file :%s passed.",FilePath);
    j = 0 ;
    for(i=0;i< Temp_var_Ini_Data.items ; i++)
    
                  
      if((strncmp(Temp_var_Ini_Data.section[i],"",strlen(Temp_var_Ini_Data.section[i])) !=0)&&
         (strncmp(Temp_var_Ini_Data.keys[i],   "",strlen(Temp_var_Ini_Data.keys[i]))    !=0)) //section、key 值不为空,写入
        
      
        /* section_temp是一个临时字符串数组,用来存储已经写过的section,
        每次执行写入前会先检查下是否已经写过了,如果没写过,就添加到这个素组中,如果在这个数组中找到了,就不再写入Ini了
        */
        retVal = SeachValueInArrary(Temp_var_Ini_Data.section[i],section_temp );
        
        if (retVal== -1)
               
          snprintf(tempText, elcount(tempText), "\\n[%s]\\n", Temp_var_Ini_Data.section[i]);
          filePutString (tempText, elcount(tempText),glbHandle);       
          strncpy (section_temp[j],Temp_var_Ini_Data.section[i]  ,elcount(section_temp[j]));
          j++ ;
        

        snprintf(tempText, elcount(tempText), "%s = %s\\n", Temp_var_Ini_Data.keys[i],Temp_var_Ini_Data.values[i]); //写入键值对
        filePutString (tempText, elcount(tempText),glbHandle); 
      
          
      
    fileClose (glbHandle);  
    
  else
  
    write("Write file :%s failed.",FilePath);
    return 0; //failed    
  
  return 1; //passed


/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
在一个中查找指定值
----------------------------------------------------------------------------------------------------
***************************************************************************************************/
long SeachValueInArrary(char target[] ,char source[][])

  
  int i ;
  
  for(i= 0;i<elcount(source);i++)
  
    if(strncmp(target,source[i],strlen(target)) ==0 )
    
      //write("Seached value %s in the arrary and the index is %d",target,i);
      return i;
    
   
  return -1 ;



  • 4️⃣ 我们再在按键’u‘,读取了INI文件后,什么操都不要做,然会按下’m‘,看下测试结果已经都写进来了

📗 更新INI文件键值对

  • 1️⃣ 我们读取了之后,可能的操作是改写其中的某个键值对,

  • 2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin文件中

  • IniAuto.can中的增加的代码:

on key 'i' //改写key


  write("*****press %c***********",this);
  updateINIvalue(0,"Tester ","Runer","",var_Ini_Data,Ini_data_path_out); // 改写第一个键值对的key,索引值是0,把Tester改成Runer
  


on key 'p' //改写value


  write("*****press %c***********",this);
  updateINIvalue(0,"Tester","Tester","https://blog.csdn.net/qq_34414530",var_Ini_Data,Ini_data_path_out); // 改写第一个键值对的value,索引值是0,
  


on key 'k' //改写value


  write("*****press %c***********",this);
  updateINIvalue(0,"Tester","Runer","https://blog.csdn.net/qq_34414530",var_Ini_Data,Ini_data_path_out); // 对key和value同时操做
  


  • 3️⃣ 头文件 IniAuto.cin中增加的代码:

/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
更改键值对,不完善,异常捕捉代码需完善
----------------------------------------------------------------------------------------------------
***************************************************************************************************/

void updateINIvalue(long index ,char section[],char keys[],char values[],struct Ini_Data Temp_var_Ini_Data,char FilePath[])
     
  if(index < Temp_var_Ini_Data.items)
  
    if(strncmp(section,"",strlen(section)) !=0)// 不等于空,就写入
    
      strncpy (Temp_var_Ini_Data.section[index],section  ,elcount(Temp_var_Ini_Data.section[index]));
    
    if(strncmp(keys,"",strlen(keys)) !=0)// 不等于空,就写入
    
      strncpy (Temp_var_Ini_Data.keys[index]   ,keys     ,elcount(Temp_var_Ini_Data.keys[index]));
    
    if(strncmp(values,"",strlen(values)) !=0)// 不等于空,就写入
    
      strncpy (Temp_var_Ini_Data.values[index] ,values   ,elcount(Temp_var_Ini_Data.values[index]));
    
     
        
     SetKeyValueToINI(FilePath, Temp_var_Ini_Data); //保存
  
  else
  
    write("index out of range.");
  




  • 4️⃣ 我们看下测试结果

🏀 先按键’u‘读取原始INI,然会按下’i‘,改写Key值:


🏀 先按键’u‘读取原始INI,然会按下p,改写value值:


🏀 先按键’u‘读取原始INI,然会按下k,改写key/value值:

📗 删除INI文件键值对

  • 1️⃣ 我们读取了之后,可能的操作是改写其中的删除某个键值对,

  • 2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin文件中

  • IniAuto.can中的增加的代码:

on key 'h' //删除键值对


  write("*****press %c***********",this);
  deleteINIItem(3,var_Ini_Data,Ini_data_path_out); // 删除Peed = 20.5


  • 3️⃣ 头文件 IniAuto.cin中增加的代码:
/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
删除键值对,这里根据索引去删除,也可以再重载函数根据key值或者value值去删除
当然也可以重载函数,传入索引数组,去批量删除,
后期有时间再继续完善
----------------------------------------------------------------------------------------------------
***************************************************************************************************/

void deleteINIItem(long index ,struct Ini_Data Temp_var_Ini_Data,char FilePath[])
     
  if(index < Temp_var_Ini_Data.items)
  
    strncpy (Temp_var_Ini_Data.section[index],""  ,elcount(Temp_var_Ini_Data.section[index]));  
    strncpy (Temp_var_Ini_Data.keys[index]   ,""  ,elcount(Temp_var_Ini_Data.keys[index]));
    strncpy (Temp_var_Ini_Data.values[index] ,""  ,elcount(Temp_var_Ini_Data.values[index]));
        
    SetKeyValueToINI(FilePath, Temp_var_Ini_Data); //保存
  
  else
  
    write("index out of range.");
  



  • 4️⃣ 我们看下测试结果

🏀 先按键’u‘读取原始INI,然会按下’h‘,删除Peed = 20.5:

📗 增加INI文件键值对

  • 1️⃣ 我们读取了之后,可能的操作是增加某个键值对

  • 2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin文件中

  • IniAuto.can中的增加的代码:

on key 'j' //增加键值对


  write("*****press %c***********",this);
  appendINIItem("Number","place","shanghai",var_Ini_Data,Ini_data_path_out); // 在[Number] 下增加一个place = shanghai,


on key 'g' //增加键值对,新的section


  write("*****press %c***********",this);
  appendINIItem("Position","place","shanghai",var_Ini_Data,Ini_data_path_out); // 在[Number] 下增加一个place = shanghai,


  • 3️⃣ 头文件 IniAuto.cin中增加的代码:
/***************************************************************************************************
----------------------------------------------------------------------------------------------------
Revision history:
Date   2022-2-18
Author mayixiaobing
增加键值对,下面的代码支持加入新的section,如果要在已有的section
-------------

以上是关于CAPL 脚本对.ini 配置文件的高阶操作的主要内容,如果未能解决你的问题,请参考以下文章

CAPL 脚本中对信号,系统变量,环境变量的 事件响应

CAPL脚本中关于相对路径/绝对路径操作的几个傻傻分不清的内置函数

CAPL脚本,数组的一些查找操作,包括查找某一个值和某一些值

CAPL读取CSV文件,像python一样简单方便

python读取/写入配置文件ini方法

Qt通过QSttings类读取*.ini配置文件