分享
 
 
 

C源码:通用C语言函数:文本文件有关操作,.CFG/.INI类配置文件读写

王朝c/c++·作者佚名  2005-05-25
窄屏简体版  字體: |||超大  

/*

通用C语言函数:文本文件有关操作,.CFG/.INI类配置文件读写。我们知道WINDOWS下的软件可以使用.INI文件

处理程序配置,那么在DOS、UNIX、AS/400上又如何才能读写.CFG/.INI类配置文件? 你可以使用本程序的有关函

数很方便地实现。注:AS/400上输入和显示[]有些问题,所以用{}代替来将section名括起。

GCFTXTF.C -- General C functions for Text File Read/Write

M.L.Y 2000.1.1

MODIFIED (YYYY.MM.DD)

M.L.Y 2000.01.01 - Creation

*/

#if __OS400__ /* AS/400 */

#include "GCFTXTFH"

#else

# include "GCFTXTF.H"

#endif

struct txt_line_flds txt_line_fld[MAX_TXT_LINE_FLD];

char CFG_ssl = '[', CFG_ssr = ']'; /* .CFG/.INI file section symbol */

int CFG_section_line_no, CFG_key_line_no, CFG_key_lines;

/* ------------------------------------------------------------------------- */

int fgetline(FILE *fp, USGC *buffer, int maxlen)

/*

Read 1 line text into *buffer from file *fp, return length actually read.

maxlen --- max. length of *buffer

CR or LF is not put into *buffer

FF(0x0C) is put into *buffer and then return

Ctrl-Z(0x1A) is put into *buffer and then return

If EOF was detected then return -1

If an error occurred then return -2

M.L.Y 1995.06.09, 07.31, 1998.9.9

*/

{

#if __OS400__ /* AS/400 */

int i;

memset(buffer, 0x00, maxlen);

if(fgets(buffer, maxlen, fp) == NULL)

{

i = strlen(buffer);

if(feof(fp) != 0)

{

if(i == 0) return -1; /* EOF */

}

else return -2; /* error */

}

i = strlen(buffer);

if(i > 0 && buffer[i-1] == '\n')

buffer[--i] = '\0';

return i;

#else

int i, j;

USGC ch1;

for(i = 0, j = 0; i < maxlen; j++)

{

if(fread(&ch1, sizeof(USGC), 1, fp) != 1)

{

if(feof(fp) != 0)

{

if(j == 0) return -1; /* EOF */

else break;

}

if(ferror(fp) != 0) return -2; /* error */

return -2;

}

else

{

if(ch1 == '\n' || ch1 == 0x00) break; /* end of line */

if(ch1 == '\f' || ch1 == 0x1A) /* '\f': Form Feed */

{

buffer[i++] = ch1;

break;

}

if(ch1 != '\r') buffer[i++] = ch1; /* ignore CR */

}

}

buffer[i] = '\0';

return i;

#endif

}

/* ------------------------------------------------------------------------- */

int copy_txt_file(void *source_file, void *dest_file)

/*

Copy source_file to dest_file

Return code:

0 -- Ok

<0 -- Error

M.L.Y 1996.7, 2000.11

*/

{

FILE *fp1, *fp2;

USGC buf[1024+1];

int rc;

if((fp1 = fopen((char *)source_file, "r")) == NULL)

return COPYF_ERR_OPEN_FILE;

rc = COPYF_ERR_CREATE_FILE;

#if __OS400__ /* AS/400 */

if((fp2 = fopen((char *)dest_file, "w, lrecl=92, ccsid=935")) == NULL)

goto copy_end;

#else

if((fp2 = fopen((char *)dest_file, "w")) == NULL) goto copy_end;

#endif

while(1)

{

rc = COPYF_ERR_READ_FILE;

memset(buf, 0x00, 1024+1);

if(fgets((char *)buf, 1024, fp1) == NULL)

{

if(mstrlen(buf) == 0)

{

if(ferror(fp1) != 0) goto copy_end;

break; /* EOF */

}

}

rc = COPYF_ERR_WRITE_FILE;

if(fputs((char *)buf, fp2) == EOF) goto copy_end;

}

rc = COPYF_OK;

copy_end:

if(fp2 != NULL) fclose(fp2);

if(fp1 != NULL) fclose(fp1);

return rc;

}

/* ------------------------------------------------------------------------- */

int split_txt_line_fld(char *txt_line, char *sep_chars)

/*

Split a text line fields info to struct txt_line_fld

Return fld number

e.g.: fld1 = fld2, fld3, "fld4", 'fld5'

key = value

M.L.Y 2000.8.2

*/

{

int i, j, k, n, stat = 0, quote_stat = 0;

char quote;

n = strlen(txt_line);

for(i = 0, j = 0, k = 0; i <= n; i++)

{

if(i >= n ||

(strchr(sep_chars, txt_line[i]) != NULL && quote_stat == 0))

{

if(stat == 0) continue;

stat = 0; /* is separate char */

txt_line_fld[k].fldsp = j;

txt_line_fld[k].fldlen = i - j;

k++;

}

else

{

if(txt_line[i] == '\'' || txt_line[i] == '\"')

{

if(quote_stat == 0)

{

quote = txt_line[i]; /* " or ' */

quote_stat = 1; /* enter " " or ' ' */

}

else

{

if(txt_line[i] == quote)

quote_stat = 0; /* withdraw from " " or ' ' */

}

}

if(stat == 1) continue;

stat = 1; /* is normal char */

j = i; /* fld start pointer */

}

}

return k; /* fld number */

}

/* ------------------------------------------------------------------------- */

char *get_txt_line_fld(char *txt_line, int fldno, char *buf)

/*

After split a text line fields info to struct txt_line_fld,

get the fldno fld to buf

Return buf

M.L.Y 2000.8.2

*/

{

memmove(buf, txt_line + txt_line_fld[fldno].fldsp,

txt_line_fld[fldno].fldlen);

buf[txt_line_fld[fldno].fldlen] = '\0';

return buf;

}

/* ------------------------------------------------------------------------- */

int split_key_val(USGC *buf, USGC **key, USGC **val)

/*

Split key=val pair:

xxx = yyyyyyyy

| | |

k1 k2 i

return:

1 --- ok

0 --- blank line

-1 --- no key, "= val"

-2 --- only key, no '='

M.L.Y 2000.8, 2000.11

*/

{

int i, k1, k2, n;

if((n = strlen((char *)buf)) < 1) return 0;

for(i = 0; i < n; i++)

if(buf[i] != ' ' && buf[i] != '\t') break;

if(i >= n) return 0;

if(buf[i] == '=') return -1;

k1 = i;

for(i++; i < n; i++)

if(buf[i] == '=') break;

if(i >= n) return -2;

k2 = i;

for(i++; i < n; i++)

if(buf[i] != ' ' && buf[i] != '\t') break;

buf[k2] = '\0';

*key = buf + k1;

*val = buf + i;

return 1;

}

/* ------------------------------------------------------------------------- */

int CFG_get_key(void *CFG_file, void *section, void *key, void *buf)

/*

Note:

section --- not include [] or {}

key --- may include blank space

blank line or begin with ';' for remarks

line end with '+' for line to be continued

Return:

0 --- ok

<0 --- error

*/

{

FILE *fp;

USGC buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];

USGC *key_ptr, *val_ptr;

int line_no, n, rc;

line_no = 0;

CFG_section_line_no = 0;

CFG_key_line_no = 0;

CFG_key_lines = 0;

#if __OS400__ /* AS/400 */

if((fp = fopen((char *)CFG_file, "r")) == NULL) return CFG_ERR_OPEN_FILE;

#else

if((fp = fopen((char *)CFG_file, "rb")) == NULL) return CFG_ERR_OPEN_FILE;

#endif

while(1) /* seek section */

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf1, MAX_CFG_BUF);

if(n < -1) goto r_cfg_end;

rc = CFG_SECTION_NOT_FOUND;

if(n < 0) goto r_cfg_end; /* EOF, not found */

line_no++;

n = mstrlen(ltrimstr(rtrimstr(buf1)));

if(n == 0 || buf1[0] == ';') continue; /* blank/remarks line */

rc = CFG_ERR_FILE_FORMAT;

if(n > 2 && ((buf1[0] == '[' && buf1[n-1] != ']') ||

(buf1[0] == '{' && buf1[n-1] != '}')))

goto r_cfg_end;

if(buf1[0] == '[' || buf1[0] == '{')

{

buf1[n-1] = 0x00;

if(mstrcmp(buf1+1, section) == 0)

break; /* section found */

}

}

CFG_section_line_no = line_no;

while(1) /* seek key */

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf1, MAX_CFG_BUF);

if(n < -1) goto r_cfg_end;

rc = CFG_KEY_NOT_FOUND;

if(n < 0) goto r_cfg_end; /* EOF, key not found */

line_no++;

CFG_key_line_no = line_no;

CFG_key_lines = 1;

n = mstrlen(ltrimstr(rtrimstr(buf1)));

if(n == 0 || buf1[0] == ';') continue; /* blank/remarks line */

rc = CFG_KEY_NOT_FOUND;

if(buf1[0] == '[' || buf1[0] == '{') goto r_cfg_end;

if(buf1[n-1] == '+') /* to be continued */

{

buf1[n-1] = 0x00;

while(1)

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf2, MAX_CFG_BUF);

if(n < -1) goto r_cfg_end;

if(n < 0) break; /* EOF */

line_no++;

CFG_key_lines++;

n = mstrlen(rtrimstr(buf2));

rc = CFG_ERR_EXCEED_BUF_SIZE;

if(n > 0 && buf2[n-1] == '+') /* to be continued */

{

buf2[n-1] = 0x00;

if(mstrlen(buf1) + mstrlen(buf2) > MAX_CFG_BUF)

goto r_cfg_end;

mstrcat(buf1, buf2);

continue;

}

if(mstrlen(buf1) + mstrlen(buf2) > MAX_CFG_BUF)

goto r_cfg_end;

mstrcat(buf1, buf2);

break;

}

}

rc = CFG_ERR_FILE_FORMAT;

if(split_key_val(buf1, &key_ptr, &val_ptr) != 1)

goto r_cfg_end;

ltrimstr(rtrimstr(key_ptr));

if(mstrcmp(key_ptr, key) != 0)

continue; /* not same key */

mstrcpy(buf, val_ptr);

break;

}

rc = CFG_OK;

r_cfg_end:

if(fp != NULL) fclose(fp);

return rc;

}

/* ------------------------------------------------------------------------- */

int CFG_set_key(void *CFG_file, void *section, void *key, void *buf)

/*

Note:

section --- not include [] or {}

key --- may include blank space

not use '+' for line to be continued

Return:

0 --- ok

<0 --- error

*/

{

FILE *fp1, *fp2;

USGC buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];

int line_no, line_no1, n, rc, rc2;

char *tmpfname;

rc = CFG_get_key(CFG_file, section, key, buf1);

if(rc <= CFG_ERR && rc != CFG_ERR_OPEN_FILE) return rc;

if(rc == CFG_ERR_OPEN_FILE || rc == CFG_SECTION_NOT_FOUND)

{

#if __OS400__ /* AS/400 */

if((fp1 = fopen((char *)CFG_file, "a, lrecl=92, ccsid=935")) == NULL)

#else

if((fp1 = fopen((char *)CFG_file, "a")) == NULL)

#endif

return CFG_ERR_CREATE_FILE;

#if __OS400__ /* AS/400 */

CFG_ssl = '{';

CFG_ssr = '}'; /* .CFG/.INI file section symbol */

#else

CFG_ssl = '[';

CFG_ssr = ']'; /* .CFG/.INI file section symbol */

#endif

if(fprintf(fp1, "%c%s%c\n", CFG_ssl, section, CFG_ssr) == EOF)

{

fclose(fp1);

return CFG_ERR_WRITE_FILE;

}

if(fprintf(fp1, "%s=%s\n", key, buf) == EOF)

{

fclose(fp1);

return CFG_ERR_WRITE_FILE;

}

fclose(fp1);

return CFG_OK;

}

if((tmpfname = tmpnam(NULL)) == NULL)

return CFG_ERR_CREATE_FILE;

#if __OS400__ /* AS/400 */

if((fp2 = fopen(tmpfname, "w, lrecl=92, ccsid=935")) == NULL)

#else

if((fp2 = fopen(tmpfname, "w")) == NULL)

#endif

return CFG_ERR_CREATE_FILE;

rc2 = CFG_ERR_OPEN_FILE;

#if __OS400__ /* AS/400 */

if((fp1 = fopen((char *)CFG_file, "r")) == NULL) goto w_cfg_end;

#else

if((fp1 = fopen((char *)CFG_file, "rb")) == NULL) goto w_cfg_end;

#endif

if(rc == CFG_KEY_NOT_FOUND)

line_no1 = CFG_section_line_no;

else /* rc = CFG_OK */

line_no1 = CFG_key_line_no - 1;

for(line_no = 0; line_no < line_no1; line_no++)

{

rc2 = CFG_ERR_READ_FILE;

n = fgetline(fp1, buf1, MAX_CFG_BUF);

if(n < 0) goto w_cfg_end;

rc2 = CFG_ERR_WRITE_FILE;

if(fprintf(fp2, "%s\n", buf1) == EOF) goto w_cfg_end;

}

if(rc != CFG_KEY_NOT_FOUND)

for( ; line_no < line_no1+CFG_key_lines; line_no++)

{

rc2 = CFG_ERR_READ_FILE;

n = fgetline(fp1, buf1, MAX_CFG_BUF);

if(n < 0) goto w_cfg_end;

}

rc2 = CFG_ERR_WRITE_FILE;

if(fprintf(fp2, "%s=%s\n", key, buf) == EOF) goto w_cfg_end;

while(1)

{

rc2 = CFG_ERR_READ_FILE;

n = fgetline(fp1, buf1, MAX_CFG_BUF);

if(n < -1) goto w_cfg_end;

if(n < 0) break;

rc2 = CFG_ERR_WRITE_FILE;

if(fprintf(fp2, "%s\n", buf1) == EOF) goto w_cfg_end;

}

rc2 = CFG_OK;

w_cfg_end:

if(fp1 != NULL) fclose(fp1);

if(fp2 != NULL) fclose(fp2);

if(rc2 == CFG_OK)

{

rc = copy_txt_file(tmpfname, CFG_file);

if(rc != 0) return CFG_ERR_CREATE_FILE;

}

remove(tmpfname);

return rc2;

}

/* ------------------------------------------------------------------------- */

int CFG_get_sections(void *CFG_file, USGC *sections[])

/*

取.CFG/.INI等配置文件的所有section名字(用[]或

{}括起的,不返回括弧),返回section个数。若出错,

返回负数。

*/

{

FILE *fp;

USGC buf1[MAX_CFG_BUF + 1];

int n, n_sections = 0, rc;

#if __OS400__ /* AS/400 */

if((fp = fopen(CFG_file, "r")) == NULL) return CFG_ERR_OPEN_FILE;

#else

if((fp = fopen(CFG_file, "rb")) == NULL) return CFG_ERR_OPEN_FILE;

#endif

while(1) /* seek section */

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf1, MAX_CFG_BUF);

if(n < -1) goto cfg_scts_end;

if(n < 0) break; /* EOF */

n = mstrlen(ltrimstr(rtrimstr(buf1)));

if(n == 0 || buf1[0] == ';') continue; /* blank/remarks line */

rc = CFG_ERR_FILE_FORMAT;

if(n > 2 && ((buf1[0] == '[' && buf1[n-1] != ']') ||

(buf1[0] == '{' && buf1[n-1] != '}')))

goto cfg_scts_end;

if(buf1[0] == '[' || buf1[0] == '{')

{

buf1[n-1] = 0x00;

mstrcpy(sections[n_sections], buf1+1);

n_sections++;

}

}

rc = n_sections;

cfg_scts_end:

if(fp != NULL) fclose(fp);

return rc;

}

/* ------------------------------------------------------------------------- */

int CFG_get_keys(void *CFG_file, void *section, USGC *keys[])

/*

取.CFG/.INI等配置文件的某个section下的所有key的

名字(key=value形式, value可用加号表示续行),返回

key个数。若出错,返回负数。

*/

{

FILE *fp;

USGC buf1[MAX_CFG_BUF + 1], buf2[MAX_CFG_BUF + 1];

USGC *key_ptr, *val_ptr;

int n, n_keys = 0, rc;

#if __OS400__ /* AS/400 */

if((fp = fopen(CFG_file, "r")) == NULL) return CFG_ERR_OPEN_FILE;

#else

if((fp = fopen(CFG_file, "rb")) == NULL) return CFG_ERR_OPEN_FILE;

#endif

while(1) /* seek section */

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf1, MAX_CFG_BUF);

if(n < -1) goto cfg_keys_end;

rc = CFG_SECTION_NOT_FOUND;

if(n < 0) goto cfg_keys_end; /* EOF, not found */

n = mstrlen(ltrimstr(rtrimstr(buf1)));

if(n == 0 || buf1[0] == ';') continue; /* blank/remarks line */

rc = CFG_ERR_FILE_FORMAT;

if(n > 2 && ((buf1[0] == '[' && buf1[n-1] != ']') ||

(buf1[0] == '{' && buf1[n-1] != '}')))

goto cfg_keys_end;

if(buf1[0] == '[' || buf1[0] == '{')

{

buf1[n-1] = 0x00;

if(mstrcmp(buf1+1, section) == 0)

break; /* section found */

}

}

while(1)

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf1, MAX_CFG_BUF);

if(n < -1) goto cfg_keys_end;

if(n < 0) break; /* EOF */

n = mstrlen(ltrimstr(rtrimstr(buf1)));

if(n == 0 || buf1[0] == ';') continue; /* blank/remarks line */

rc = CFG_KEY_NOT_FOUND;

if(buf1[0] == '[' || buf1[0] == '{')

break; /* another section */

if(buf1[n-1] == '+') /* to be continued */

{

buf1[n-1] = 0x00;

while(1)

{

rc = CFG_ERR_READ_FILE;

n = fgetline(fp, buf2, MAX_CFG_BUF);

if(n < -1) goto cfg_keys_end;

if(n < 0) break; /* EOF */

n = mstrlen(rtrimstr(buf2));

rc = CFG_ERR_EXCEED_BUF_SIZE;

if(n > 0 && buf2[n-1] == '+') /* to be continued */

{

buf2[n-1] = 0x00;

if(mstrlen(buf1) + mstrlen(buf2) > MAX_CFG_BUF)

goto cfg_keys_end;

mstrcat(buf1, buf2);

continue;

}

if(mstrlen(buf1) + mstrlen(buf2) > MAX_CFG_BUF)

goto cfg_keys_end;

mstrcat(buf1, buf2);

break;

}

}

rc = CFG_ERR_FILE_FORMAT;

if(split_key_val(buf1, &key_ptr, &val_ptr) != 1)

goto cfg_keys_end;

ltrimstr(rtrimstr(key_ptr));

mstrcpy(keys[n_keys], key_ptr);

n_keys++;

}

rc = n_keys;

cfg_keys_end:

if(fp != NULL) fclose(fp);

return rc;

}

/* ------------------------------------------------------------------------- */

int read_txt_line(void *TXT_file, int line_no, void *buf)

/*

读文本文件中指定行号(以1始计)的内容到buf

返回行内容长度,出错返回负数。

*/

{

FILE *fp;

int lno, n1;

USGC buf1[256];

if((fp = fopen((char *)TXT_file, "r")) == NULL) return TXTF_ERR_OPEN_FILE;

for(lno = 0; lno < line_no; lno++)

{

memset(buf1, 0x00, 256);

if(fgets((char *)buf1, 255, fp) == NULL)

{

n1 = mstrlen(buf1);

if(n1 == 0)

{

if(ferror(fp) != 0)

{

fclose(fp);

return TXTF_ERR_READ_FILE;

}

break;

}

break;

}

}

if(lno < line_no)

{

fclose(fp);

return TXTF_ERR_NOT_FOUND;

}

n1 = mstrlen(buf1);

if(n1 > 0 && buf1[n1-1] == '\n') buf1[--n1] = 0x00;

mstrcpy(buf, buf1);

fclose(fp);

return n1;

}

/* ------------------------------------------------------------------------- */

int seek_txt_line(void *TXT_file, void *line_tag, void *buf)

/*

查找文本文件中以line_tag内容开始的行,读其内容到

buf,返回行号(以1始计),出错返回负数。

*/

{

FILE *fp;

int line_no, n, n1;

USGC buf1[256];

n = mstrlen(line_tag);

if((fp = fopen((char *)TXT_file, "r")) == NULL) return TXTF_ERR_OPEN_FILE;

for(line_no = 1; ; line_no++)

{

memset(buf1, 0x00, 256);

if(fgets((char *)buf1, 255, fp) == NULL)

{

n1 = mstrlen(buf1);

if(n1 == 0)

{

if(ferror(fp) != 0)

{

fclose(fp);

return TXTF_ERR_READ_FILE;

}

fclose(fp); /* eof */

return TXTF_ERR_NOT_FOUND;

}

if(mstrncmp(buf1, line_tag, n) == 0) break;

fclose(fp); /* eof */

return TXTF_ERR_NOT_FOUND;

}

if(mstrncmp(buf1, line_tag, n) == 0) break;

}

n1 = mstrlen(buf1);

if(n1 > 0 && buf1[n1-1] == '\n') buf1[--n1] = 0x00;

mstrcpy(buf, buf1);

fclose(fp);

return line_no;

}

/* End of file */

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有