使⽤c语⾔实现INI⽂件的读写
INI⽂件是Windows上独有的⼀种存储结构,这只是Windows下发明的存储结构,也有很多类似的,⽐如xml!
就说⼀下TXT⽂本
是按⾏读取,这就是它的格式!
⽽xml是类似⼆叉树的带层次结构的存储⽅式
INI则是以键值的⽅式将数据对应起来,类似数据库⼀样!
在Windows上我们可以使⽤⼀些⾃带API实现对INI⽂件的读取写⼊,但是在其它系统平台上就不可以了,这⾥是博主在开发跨平台SDT⼯具包时,写的⼀款对INI⽂件操作的函数
在开始之前我们需要编写⼀些辅助函数,因为这些存储结构,都是对字符进⾏处理,我们先读⼊内存,然后开始字符流处理,这⾥值得注意的是!
所以需要编写⼀些CharString处理字符类,这⾥是从CharString库⾥copy出来的,这个库是我开源的,你可以在我的博客SDT分类⾥到这个库的介绍以及源码!
//获取⽂本所在⾏
int GetStrTxTIndx(char* m_str,const char* Str){
if (m_str == NULL || Str == NULL){
return 0;
}
int StrSize = strlen(Str);
if (StrSize <= 0){
return 0;
}
int Str_m_str = strlen(m_str);
int m_str_index = 0;/*⼆次循环坐标*/
int y = 0;
for (int i = 0; i <= Str_m_str - 1; i++/*加⼀是因为i从0开始,下⽅循环是size+1是为了将坐标移动到下个字符*/){
y = 0;
m_str_index = i;
for (int j = 0; j <= StrSize - 1; ++j, ++m_str_index){
if (Str[j] == m_str[m_str_index]){
y += 1;
}
if (y == StrSize){
return i + 1;
}
if (Str[j] != m_str[m_str_index]){
break;
}
}
}
return 0;
}
//获取⼀⾏⽂本
char* GetLineTxT(char* m_str,int LineIndex = 1) {
if (LineIndex == 0){
return 0;
}
if (m_str == NULL) {
return 0;
}
int l = 0;
char *yun = NULL;
int j = 0;
int u = 0;
for (int i = 0; i <= strlen(m_str) + 1/*包含\0*/; ++i) {
++l;
if (l != LineIndex)
u = i + 1;//+1跳过\n 这⾥递增1后⾯已经忽略0因为已经不是第⼀⾏坐标 }
if (l == LineIndex) {
//判断此⾏多长⽤于分配内存
for (j = u;; ++j) {
if (m_str[j] == '\n' || m_str[j] == '\0') {
int size = 0;
if (u == 0){//防⽌从0下标导致计算实际长度少1,因为额外的1要⽤来\0 size = j + 1; //+1是因为分配内存不是从0做下标所以需要判断是否为0 }
else{
size = j;
}
yun = (char*)malloc(size + 1); //多分配额外字节,\0
memset(yun, 0, size + 1);
break;
}
}
int in = 0;
for (int n = u; n <= j; ++n, ++in) {
yun[in] = m_str[n];
}
return yun;
}
}
}
//获取⽂本多少⾏
int GetLineNum(char* m_str){
if (m_str == NULL){
return 0;
}
int Size = 0;
for (int i = 0; i <= strlen(m_str)-1; ++i){
if (m_str[i] == '\n'){
++Size;
}
if (m_str[i] == '\0'){
if (m_str[i - 1] != '\n'){
Size++;
}
return Size;
}
}
return Size;
}
//判断⽂本是否存在
bool JumpTxTExits(char* m_str,char *Str){
if (GetStrTxTIndx(m_str,Str) == 0){
return false;
}
return true;
}
//判断⽂本在第⼏⾏
int GetTxTLineNum(char* m_str,char *Str){
if (Str == NULL || m_str == NULL){
return NULL;
}
char *str1 = NULL;
int i = 1;
int u = GetLineNum(m_str);
while (1){//查这个⽂本格式在第⼏⾏⾥
str1 = GetLineTxT(m_str,i);
return NULL;
}
if (JumpTxTExits(str1, Str) == true){
break;
}
if (i > u){
return 0;
}
++i;
}
return i;
}
INI读取:
//ini
char* iniGet(char *FileName, char* Primary_Key, char* Key,bool Speck = true){
//判断是否为空
if (Primary_Key == NULL || Key == NULL||FileName == NULL){
return NULL;
}
//格式合成
char *FormatStr = (char*)malloc(strlen(Primary_Key) + 3); //[]\0
memset(FormatStr, 0, strlen(Primary_Key) + 3);
sprintf(FormatStr, "[%s]", Primary_Key);
//读⼊⽂件
FILE *fp = fopen(FileName, "r");
if (fp == NULL){
return NULL;
}
fseek(fp, 0L, SEEK_END);
signed long long int size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char *txt = (char*)malloc(size + 1);
memset(txt, 0, size+1);
fread(txt, size, 1, fp);
fclose(fp);
//获取主键值的位置
int y = GetStrTxTIndx(txt, FormatStr);
if (y == 0){
return NULL;
}
/
/循环读取当前键值下的所有值,除遇得下⼀个键值
for (int i = y; i <= size-1; ++i){
if (txt[i] == '\n'){
for (int j = i; j <= size - 1; ++j){
if (txt[j] == '['){ //到了第⼆个键值
for (int h = j; h <= size - 1; ++h){
txt[h] = '\0';
}
goto t; //读取完成后不要继续读取了,直接跳⼊下⼀个处理环境,因为我们已经得到当前主键值下的所有内容了 }
}
}
}
t:
//判断⽂本在第⼏⾏
int Lin = GetTxTLineNum(txt, Key);
if (Lin == 0){
return NULL;
}
}
//获取所在⾏⽂本
char* st = GetLineTxT(txt, Lin);
c++strcpy函数用法char* stcopy = (char*)malloc(strlen(st) + 1);
memset(stcopy, 0, strlen(st) + 1);
strcpy(stcopy, st);
free(st);
st = NULL;
int yunsi = 0;
//开始处理
for (int i = 0; i <= strlen(stcopy) - 1; ++i){
if (stcopy[i] == '='){
if (Speck){
if (stcopy[i + 1] == ' '){ //忽略开头空格
i = i + 1;
for (; i <= strlen(stcopy) - 1; ++i){
if (stcopy[i] != ' ')break;
}
i = i - 1;
}
}
for (int j = i + 1; j<=strlen(stcopy)-1; ++j){
++yunsi;
}
char* data = (char*)malloc(yunsi + 1);
if (data == NULL){
return NULL;
}
memset(data, 0, yunsi + 1);
int hk = 0;
for (int j = i + 1; j <= strlen(stcopy) - 1; ++j){ if (stcopy[j] == '\n'){//如果遇到⽂件尾⼀样退出 return data;
}
data[hk++] = stcopy[j];
}
return data;
}
}
return 0;
}
⽰列:
ini:
[key1]
Test = test⽂本
test=这⾥是不忽略空格的⽂本
[key2]
Test=test
代码:
iniGet("","key1","Test");
输出
test⽂本
//ini写⼊
//ini
int iniSet(char *FileName, char* Primary_Key, char* Key, char* Data,bool Speck = true){ if (Primary_Key == NULL || Key == NULL || FileName == NULL){
return NULL;
}
char *FormatStr = (char*)malloc(strlen(Primary_Key) + 3); //[]\0
memset(FormatStr, 0, strlen(Primary_Key) + 3);
sprintf(FormatStr, "[%s]", Primary_Key);
FILE *fp = fopen(FileName, "r");
char* flun = NULL; //⽤于保存后数据
if (fp == NULL){
return NULL;
}
fseek(fp, 0L, SEEK_END);
signed long long int size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char *txt = (char*)malloc(size + 1);
memset(txt, 0, size + 1);
flun = (char*)malloc(size + 1);
memset(flun, 0, size + 1);
char* jnmhand = (char*)malloc(size + 1+strlen(Data)); //保存头
memset(jnmhand, 0, size + 1 + strlen(Data));
fread(txt, size, 1, fp);
int y = GetStrTxTIndx(txt, FormatStr);
if (y == 0){
return NULL;
}
int yi = 0;
if (y != 1){
for (int i = 0; i <= y - 1; ++i){
jnmhand[i] = txt[i];
}
}
for (int i = y; i <= size - 1; ++i){
flun[yi++] = txt[i-1];
if (txt[i] == '\n'){
for (int j = i; j <= size - 1; ++j){
flun[yi++] = txt[j];
if (txt[j] == '['){ //到了第⼆个键值
for (int h = j; h <= size - 1; ++h){
//flun[yi++] = txt[h];
txt[h] = '\0';
}
goto t;
}
}
}
}
t:
int Lin = GetTxTLineNum(flun, Key);
if (Lin == 0){
return NULL;
}
char* setdata = (char*)malloc(size + strlen(Data) + 1);
memset(setdata, 0,size + strlen(Data) + 1);
int nn = 0;
int gh = 0;
bool kj = false; //防⽌修改数据时再次遇到=
for (int i = 0; i <= strlen(flun) - 1; ++i){
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论