详解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
中代码:
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
中代码:
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;
}
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
}
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++;
}
}
}
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.cin
中 getKeyValueFromINI
函数的注释
7️⃣ 按键’u‘
,看下测试结果:
我们已经把ini的键值对都转换为了CAPl的数组类型,那么这样我们在下一步无论怎么去批量读,改写,删除
批量写入代码讲解
- 1️⃣ 我们读取了之后,可能的操作是改写,删除,添加,甚至是新建操作,那么这一系列操作之后,我们还要保存到原来的INI文件的。
- 2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在
IniAuto.cin
文件中
IniAuto.can
中的增加的代码:
on key 'm'
{
write("*****press m***********");
SetKeyValueToINI(Ini_data_path_out,var_Ini_Data);
}
3️⃣ 头文件 IniAuto.cin
中增加的代码:
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 值不为空,写入
{
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
}
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
中增加的代码:
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
中增加的代码:
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
中增加的代码:
void appendINIItem(char section[],char keys[],char values[],struct Ini_Data Temp_var_Ini_Data,char FilePath[])
{
long retIndex ;
long items;
long i ;
if((strncmp(section,"",strlen(section)) !=0)&&
(strncmp(keys ,"",strlen(keys)) !=0)) //section、key 值不为空,写入
{
items = Temp_var_Ini_Data.items ;
retIndex = SeachValueInArrary(section,Temp_var_Ini_Data.section);
if (retIndex == -1)//如果是新的section,直接尾处追加
{
strncpy (Temp_var_Ini_Data.section[items],section ,elcount(Temp_var_Ini_Data.section[items]));
strncpy (Temp_var_Ini_Data.keys[items] ,keys ,elcount(Temp_var_Ini_Data.keys[items]));
strncpy (Temp_var_Ini_Data.values[items] ,values ,elcount(Temp_var_Ini_Data.values[items]));
}
else //如果是已有section,从索引处,向后顺移
{
for(i= items;i > retIndex ;i--)
{
strncpy (Temp_var_Ini_Data.section[i],Temp_var_Ini_Data.section[i-1] ,elcount(Temp_var_Ini_Data.section[i]));
strncpy (Temp_var_Ini_Data.keys[i] ,Temp_var_Ini_Data.keys[i-1] ,elcount(Temp_var_Ini_Data.keys[i]));
strncpy (Temp_var_Ini_Data.values[i] ,Temp_var_Ini_Data.values[i-1] ,elcount(Temp_var_Ini_Data.values[i]));
}
strncpy (Temp_var_Ini_Data.section[retIndex],section ,elcount(Temp_var_Ini_Data.section[retIndex]));
strncpy (Temp_var_Ini_Data.keys[retIndex] ,keys ,elcount(Temp_var_Ini_Data.keys[retIndex]));
strncpy (Temp_var_Ini_Data.values[retIndex] ,values ,elcount(Temp_var_Ini_Data.values[retIndex]));
}
Temp_var_Ini_Data.items = items + 1;
SetKeyValueToINI(FilePath, Temp_var_Ini_Data); //保存
}
}
4️⃣ 我们看下测试结果
? 先按键’u‘
读取原始INI,然会按下’j‘,
在已有的section新加一个key/value:
? 先按键’u‘
读取原始INI,然会按下’g‘,
新建section以及key/value:
新建INI文件
1️⃣ 我们也可以直接新建一个键值对文件,不需要提前读取
2️⃣ 我们按照编程习惯,控制语句放在IniAuto.can文件中,函数和全局变量放在IniAuto.cin
文件中
IniAuto.can
中的增加的代码,下面是新增两个参数:
on key 'f' //新建ini文件
{
write("*****press %c***********",this);
var_Ini_Data.items = 2;
strncpy (var_Ini_Data.section[0],"test" ,elcount(var_Ini_Data.section[0]));
strncpy (var_Ini_Data.keys[0] ,"para1" ,elcount(var_Ini_Data.keys[0]));
strncpy (var_Ini_Data.values[0] ,"1234" ,elcount(var_Ini_Data.values[0]));
strncpy (var_Ini_Data.section[1],"test" ,elcount(var_Ini_Data.section[0]));
strncpy (var_Ini_Data.keys[1] ,"para2" ,elcount(var_Ini_Data.keys[0]));
strncpy (var_Ini_Data.values[1] ,"4567" ,elcount(var_Ini_Data.values[0]));
SetKeyValueToINI(Ini_data_path_out,var_Ini_Data);
}
3️⃣ 头文件IniAuto.cin中
增加的代码:
无新增.cin代码
4️⃣ 我们看下测试结果
到此这篇关于CAPL 脚本对.ini 配置文件的高阶操作的文章就介绍到这了,更多相关CAPL 脚本.ini 配置文件操作内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341