博客 / 詳情

返回

編程把INI文件轉換成XML文件

來自宋勁波老師《linuxc》的習題

INI文件是一種很常見的配置文件,很多Windows程序都採用這種格式的配置文件,在Linux系統中Qt程序通常也採用這種格式的配置文件。比如:

;Configuration of http
[http]
domain=www.mysite.com
port=8080
cgihome=/cgi-bin

;Configuration of db
[database]
server = mysql
user = myname
password = toopendatabase

一個配置文件由若干個Section組成,由[]括號括起來的是Section名。每個Section下面有若干個key = value形式的鍵值對(Key-value Pair),等號兩邊可以有零個或多個空白字符(空格或Tab),每個鍵值對佔一行。以;號開頭的行是註釋。每個Section結束時有一個或多個空行,空行是僅包含零個或多個空白字符(空格或Tab)的行。INI文件的最後一行後面可能有換行符也可能沒有。
現在XML興起了,INI文件顯得有點土。現在要求編程把INI文件轉換成XML文件
首先我們自己創建一個文本文件ini.txt如下:
image.png

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define MAX_LINE 128

//初始化buf用'\0'填充
void ainit( char *buf )
{
    int i;
    for ( i = 0; i< MAX_LINE; i++ ) {
        buf[i] = '\0';
    }
}
//將'\n'替換為'\0'
void adell( char *buf )
{
    int i;
    for ( i = 0; buf[i] != '\0'; i++ ) {
        if ( buf[i] =='\n' ) {
            buf[i] = '\0';
        }
    }
}
//去除數組中的'\t','空格'
void abdel( char *buf )
{
    int i = 0, j = 0;
    for ( ; buf[i] != '\0'; i++ ) {
        if ( (buf[i] == '\t') || (buf[i] == ' ') ) {
            j = i;
            while ( buf[j] != '\0' ) {
                buf[j] = buf[j + 1];
                j++;
            }
            i = i - 1;
        }
    }
}

int main(){
    FILE *fp_xml,*fp_ini;
    //定義緩衝區
    char buf[MAX_LINE] = {0};
    char dbuf[MAX_LINE] = {0};
    char ch = '\0';
    char *kv, *key, *val;
    int i = 0;

    fp_ini = fopen("ini.txt","r+");
    fp_xml = fopen("xml.txt","w+");

    if ( fp_ini == NULL ) {
            perror("config.ini is not exist\n");
            exit(1);
    }
    if ( fp_xml == NULL  ) {
        perror("xml is not exist\n");
        exit(1);
    }

    while((ch = fgetc(fp_ini)) != EOF){
        if(ch == ';'){
            //該語句控制</http>的打印和兩個section之間的空一行
            if( buf[0] != '\0' )//只有,此時已經生成了<http>,由buf緩存,且並未flush時才成立
                                //所以該條件旨在生成第二個,即</http>
                fprintf( fp_xml, "</%s>\n\n", buf );//多空一行
                //由於這個語句包含在while中(;語句轉換之前),所以最後一個</xxxx>無法生成
                //見line:105來生成
            //然後再進行;部分的轉換
            fgets(buf,MAX_LINE,fp_ini);
            adell(buf);//將;Configuration of http\n後跟的\n去掉,後面我們自己控制換行
            fprintf(fp_xml,"<!-- %s -->\n",buf);
            
            fflush(NULL);//該語句是確保所有文件寫操作從cache傳給內核到磁盤,不寫也不影響
            continue;
        }
        if(ch == '['){
            ainit(buf);//繼續利用buf進行[http]的轉換
            for(i = 0; (ch = fgetc(fp_ini)) != ']'; i++ ) {
                buf[i] = ch;//注意此處不能用fgets,我們只要[]內部的字符,不要括號和\n
            }
            fprintf(fp_xml,"<%s>\n",buf);
            fflush(NULL);
            continue;
        }
        if((ch != '\n') && (ch != '\t') && (ch != ' ')){
            ainit(dbuf);
            fgets(dbuf,MAX_LINE,fp_ini);//此處便可以直接獲一行
            // for( i = 0; (ch = fgetc(fp_ini)) != '\n' ; i++ ) {
            //     dbuf[i] = ch;
            // }//如果用這個循環來給dbuf賦值會gdb提示索引越界,未找到原因
            adell(dbuf);//同上
            abdel(dbuf);//前面如果有\t,以及中間夾的空格等都去掉

            kv = dbuf;
            key = strtok(kv,"=");
            val = strtok(NULL,"=");//獲取第一次截去後剩餘的字符串
            fprintf(fp_xml,"   <%c%s>%s</%c%s>\n",ch,key,val,ch,key);//注意此處ch
            //當前fgets讀取的一行少了第一個字符(他被while中ch = fgetc()讀去了,所以要把它補上)
            fflush(NULL);
            continue;
        }
    }

    fprintf(fp_xml, "</%s>", buf);
    fclose(fp_xml);
    fclose(fp_ini);
    return 0;
}

參考https://www.cnblogs.com/shish...
這種寫法應該時間複雜度高一點,但是可讀性好一點,適合我這個新手!注意他的代碼中if(3)丟失了第一個字符:
fprintf(fp_xml," <%c%s>%s</%c%s>\n",ch,key,val,ch,key);//注意此處ch
當前fgets讀取的一行少了第一個字符(他被while中ch = fgetc()讀去了,所以要把它補上)

好了,讓我們運行一下,看看結果吧,結果保存到了xml.txt(自動生成的),結果如下:
image.png

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.