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) {if (m_str[i] == '\n') {++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要用来\0size = j + 1;    //+1是因为分配内存不是从0做下标所以需要判断是否为0}else{size = j;}yun = (char*)malloc(size + 1);  //多分配额外字节,\0memset(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);if (str1 == NULL){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);    //[]\0memset(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);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("file.txt","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);  //[]\0memset(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){if (flun[i] == '\n'){++nn;}if (nn == Lin - 1){    //代表已经到要修改数据行的头,因为\n在尾++nn;for (int j = i; j <= strlen(flun) - 1; ++j){ //寻找=setdata[gh++] = flun[j];if (kj == false){//kj = true;if (flun[j] == '='){//寻找有效数据if (Speck){j = j + 1;for (; j <= strlen(flun); ++j){  //寻找有效数据if (flun[j] != ' '){break;}}j = j - 1;i = j;}int n = 0;for (; n <= strlen(Data) - 1; ++n){setdata[gh++] = Data[n];}for (;;){++i;if (flun[i] == '\n' || flun[i] == '\0'){break;}}//i = i + n;break;}}}}setdata[gh++] = flun[i];}strcat(jnmhand, setdata);//内存释放free(txt);free(setdata);//数据写入fp = fopen(FileName, "w");if (fp == NULL){return 0;}fwrite(jnmhand, strlen(jnmhand), 1, fp);fclose(fp);return 0;
}

用法

iniSet("C:\\Users\\ZZH\\Desktop\\test.ini", "uu", "kk"," k");

完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//获取文本所在行
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) {if (m_str[i] == '\n') {++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要用来\0size = j + 1;    //+1是因为分配内存不是从0做下标所以需要判断是否为0}else{size = j;}yun = (char*)malloc(size + 1);  //多分配额外字节,\0memset(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);if (str1 == NULL){return NULL;}if (JumpTxTExits(str1, Str) == true){break;}if (i > u){return 0;}++i;}return i;
}
//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);    //[]\0memset(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);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
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);  //[]\0memset(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){if (flun[i] == '\n'){++nn;}if (nn == Lin - 1){    //代表已经到要修改数据行的头,因为\n在尾++nn;for (int j = i; j <= strlen(flun) - 1; ++j){ //寻找=setdata[gh++] = flun[j];if (kj == false){//kj = true;if (flun[j] == '='){//寻找有效数据if (Speck){j = j + 1;for (; j <= strlen(flun); ++j){  //寻找有效数据if (flun[j] != ' '){break;}}j = j - 1;i = j;}int n = 0;for (; n <= strlen(Data) - 1; ++n){setdata[gh++] = Data[n];}for (;;){++i;if (flun[i] == '\n' || flun[i] == '\0'){break;}}//i = i + n;break;}}}}setdata[gh++] = flun[i];}strcat(jnmhand, setdata);//内存释放free(txt);free(setdata);//数据写入fp = fopen(FileName, "w");if (fp == NULL){return 0;}fwrite(jnmhand, strlen(jnmhand), 1, fp);fclose(fp);return 0;
}
int main()
{iniSet("C:\\Users\\ZZH\\Desktop\\test.ini", "uu", "kk"," k");getchar();return 0;
}

使用c语言实现INI文件的读写相关推荐

  1. 在VB中INI文件的读写、删除(对中文支持很好)

    很多时候我们编一个程序不一定要用到注册表来保存设置(如果说一个程序没有设置就不算好程序了).INI是一个很好的选择.有人说,Savesetting是一个不错的选择,但是我了解到,不能永久的保存(起码在 ...

  2. C# ini文件的读写

    ini文件的读写 using System; using System.IO; using System.Runtime.InteropServices; using System.Text;name ...

  3. C语言实现wav文件的读写

    C语言实现wav文件的读写 wav文件格式 //wav.h typedef unsigned char uint8_t; typedef signed char int8_t; typedef uns ...

  4. 语言 读ini文件_让C语言的调试更加高大上

    一般在写一个项目的时候,为了更直观的调试,我们在程序里都会打printf调试语句,随着项目越写越多,printf也会越来越多,但项目准备结尾的时候,这时候开始优化就会发现,你想完全把printf语句都 ...

  5. linux C语言 对本地文件进行读写操作

    linux C语言 对本地文件进行最简单读写操作 读取json文件 保存json文件 读取json文件 对本地以cjson格式保存的文本进行读取 /* 读取json文件 */ const char* ...

  6. .ini文件的读写操作

    一·写入ini文件 1·写入字符串至ini文件 BOOL WritePrivateProfileString(   LPCTSTR lpAppName,  // pointer to section ...

  7. go语言的ini文件配置读取

    项目中我们可能经常要读取配置文件.那么如何读取自己写的配置文件呢?答案是反射.下面举例mysql的配置文件读取的具体操作代码. 1.首先建立myconfig.ini文件,并写入以下内容: [mysql ...

  8. SLAM|C语言实现对文件的读写

    文章目录 前言 一 文件中的数据格式: 二 C语言实现对上述文件的读取 前言 由于项目中需要将C++的实现全部改为C代码,以便后续下到核心板里进行落地.这里简单总结下C语言对wheel.imu以及uw ...

  9. C语言中对文件的读写操作

    编写程序,实现输入10个数,将这10个数按照从小到大的顺序排列,并将写入data.txt文件中 #include <stdio.h> #include <string.h>in ...

最新文章

  1. 就业丨速成班出来的AI人才,老板到底要不要?
  2. easypoi教程_SpringBoot图文教程17—上手就会 RestTemplate 使用指南
  3. 3Linux内存映射,mmap()函数
  4. E:Sleeping Schedule(DP)
  5. erlang下lists模块sort(排序)方法源码解析(二)
  6. js中解析json字符串
  7. openwabmail问题解决方法
  8. Ubuntu安装JDK,搭建java环境
  9. Elasticsearch:Simulate index API
  10. 泛化误差,偏差方差分解
  11. HTML学生个人网站作业设计:动漫网站设计——蜡笔小新(9页) HTML+CSS+JavaScript 简单DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载
  12. 比较JPG、PNG、GIF、BMP图片格式
  13. CV(1) : 光 颜色 颜色空间
  14. JSD-2204-反射-Day17
  15. Pytesseract图片识别结果箭头符号去除
  16. 《rust死灵书》阅读笔记
  17. Windows10 电脑上配置 Docker 环境
  18. 当前目录不对导致的错误
  19. ORAN专题系列-16:5G O-RAN FrontHaul前传接口的网络配置管理协议netconf
  20. 专利编写——发明专利请求书

热门文章

  1. linux服务器知识学习:linux简介与linux的发行版
  2. 设计代码说明什么是多态性?如何实现多态?(代码中要写注释解释)_狗屎一样的代码!快,重构我!...
  3. ubuntu18.04彻底卸载mysql5.7,图文详解
  4. matlab读取trmm,基于Matlab的TRMM3B43数据处理的思维过程与技术流程
  5. 电脑课装b专用代码_JavaScript无形装X,最为致命
  6. 前格式 直接将转换为当_如何将word转化为PDF格式?1分钟学会文档转换
  7. python 中定义的函数 如何在main中调用_在python中,在定义类时自动运行函数的方法?_class_酷徒编程知识库...
  8. pdo mysql_num_rows_PHP-mysql_num_rows()期望参数1为资源,给定布尔...
  9. 5g pdu session_设备 | NEC被选为NTT DOCOMO独立5G移动核心的供应商
  10. 网关转发其他微服务后头信息拿不到_微服务之基于Zuul自研服务网关