写了个INI转化为XML的小程序,利用有限状态机实现的。很简单,把INI文件中的内容一行一行地读取进一个buffer里面,然后对这个buffer进行解析,最后转化为XML的格式再写进XML文件里面。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include
<
stdio.h
>
#include < stdlib.h >
#include < string .h >
#define BUFFER_SIZE 512
#define TRUE 1
#define FALSE 0
typedef enum _state
{
STATE_NONE = 0 ,
STATE_COMMENT,
STATE_SECTION,
STATE_SECTION_END,
STATE_KEY,
} stateType;
char gSection[BUFFER_SIZE];
static int gSectionIsEmpty( void )
{
for ( int index = 0 ; index < BUFFER_SIZE; ++ index)
{
if (gSection[index] != 0x00 )
{
return FALSE;
}
}
return TRUE;
}
static stateType getStateType( const char ch)
{
stateType state = STATE_NONE;
if (ch == ' ; ' )
state = STATE_COMMENT;
else if (ch == ' [ ' )
state = STATE_SECTION;
else if (ch == ' \0 ' || ch == ' \n ' || ch == ' ' || ch == ' \t ' )
state = STATE_SECTION_END;
else
state = STATE_KEY;
return state;
}
#define KEY_LEN 128
#define VALUE_LEN 256
static void parse_key_and_value( const char * line, char * buffer)
{
char key[KEY_LEN] = { 0 };
char value[VALUE_LEN] = { 0 };
for ( int index = 0 ; * line != ' \0 ' ; ++ line)
{
if ( * line != ' \t ' && * line != ' ' && * line != ' = ' )
{
key[index ++ ] = * line;
}
else
{
key[index] = ' \0 ' ;
break ;
}
}
for (; * line != ' \0 ' ; ++ line)
{
if ( * line == ' \t ' || * line == ' ' || * line == ' = ' )
continue ;
else
break ;
}
for ( int index = 0 ; * line != ' \0 ' ; ++ line)
{
if ( * line != ' \t ' && * line != ' ' && * line != ' = ' )
{
value[index ++ ] = * line;
}
else
{
value[index] = ' \0 ' ;
break ;
}
}
sprintf(buffer, " \t<%s>%s</%s>\n " , key, value, key);
return ;
}
static void iniParse( const char * line, FILE * fpXML)
{
char writeBuffer[BUFFER_SIZE] = { 0 };
stateType state = getStateType( * line);
switch (state)
{
case STATE_COMMENT:
line ++ ;
sprintf(writeBuffer, " <!-- %s -->\n " , line);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
break ;
case STATE_SECTION:
line ++ ;
for ( int index = 0 ; index < BUFFER_SIZE && * line != ' \0 ' ; ++ line)
{
if ( * line != ' ] ' )
{
gSection[index ++ ] = * line;
}
else
{
gSection[index] = ' \0 ' ;
sprintf(writeBuffer, " <%s>\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
}
}
break ;
case STATE_SECTION_END:
if (gSectionIsEmpty() == FALSE)
{
sprintf(writeBuffer, " </%s>\n\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
memset(gSection, 0x00 , sizeof (gSection));
}
break ;
case STATE_KEY:
parse_key_and_value(line, writeBuffer);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
break ;
default :
break ;
}
return ;
}
static void createXML( const char * iniName, char * xml)
{
for ( int index = 0 ; index < 20 ; ++ index)
{
if (iniName[index] != ' . ' && iniName[index] != ' \0 ' )
{
xml[index] = iniName[index];
}
else
{
strcat(xml, " .xml " );
break ;
}
}
return ;
}
static void writeTheLastSectionEnd(FILE * fpXML)
{
char writeBuffer[BUFFER_SIZE] = { 0 };
sprintf(writeBuffer, " </%s>\n\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
return ;
}
static void iniToxml( const char * iniName)
{
char xmlName[ 20 ] = { 0 };
createXML(iniName, xmlName);
FILE * fpINI = fopen(iniName, " r " );
FILE * fpXML = fopen(xmlName, " a+ " );
if (fpINI == NULL || fpXML == NULL)
{
fprintf(stderr, " open ini/xml file failed.\n " );
return ;
}
char line[BUFFER_SIZE] = { 0 };
while (fgets(line, BUFFER_SIZE, fpINI))
{
line[strlen(line) - 1 ] = ' \0 ' ;
iniParse(line, fpXML);
memset(line, 0x00 , sizeof (line) );
}
writeTheLastSectionEnd(fpXML);
fclose(fpINI);
fclose(fpXML);
return ;
}
int main( int argc, char * argv[])
{
if (argc < 2 )
{
fprintf(stdout, " usage: ./iniToxml <*.ini> (<*.ini>, ...) " );
return - 1 ;
}
for ( int i = 1 ; i < argc; ++ i)
{
iniToxml(argv[i]);
}
return 0 ;
}
#include < stdlib.h >
#include < string .h >
#define BUFFER_SIZE 512
#define TRUE 1
#define FALSE 0
typedef enum _state
{
STATE_NONE = 0 ,
STATE_COMMENT,
STATE_SECTION,
STATE_SECTION_END,
STATE_KEY,
} stateType;
char gSection[BUFFER_SIZE];
static int gSectionIsEmpty( void )
{
for ( int index = 0 ; index < BUFFER_SIZE; ++ index)
{
if (gSection[index] != 0x00 )
{
return FALSE;
}
}
return TRUE;
}
static stateType getStateType( const char ch)
{
stateType state = STATE_NONE;
if (ch == ' ; ' )
state = STATE_COMMENT;
else if (ch == ' [ ' )
state = STATE_SECTION;
else if (ch == ' \0 ' || ch == ' \n ' || ch == ' ' || ch == ' \t ' )
state = STATE_SECTION_END;
else
state = STATE_KEY;
return state;
}
#define KEY_LEN 128
#define VALUE_LEN 256
static void parse_key_and_value( const char * line, char * buffer)
{
char key[KEY_LEN] = { 0 };
char value[VALUE_LEN] = { 0 };
for ( int index = 0 ; * line != ' \0 ' ; ++ line)
{
if ( * line != ' \t ' && * line != ' ' && * line != ' = ' )
{
key[index ++ ] = * line;
}
else
{
key[index] = ' \0 ' ;
break ;
}
}
for (; * line != ' \0 ' ; ++ line)
{
if ( * line == ' \t ' || * line == ' ' || * line == ' = ' )
continue ;
else
break ;
}
for ( int index = 0 ; * line != ' \0 ' ; ++ line)
{
if ( * line != ' \t ' && * line != ' ' && * line != ' = ' )
{
value[index ++ ] = * line;
}
else
{
value[index] = ' \0 ' ;
break ;
}
}
sprintf(buffer, " \t<%s>%s</%s>\n " , key, value, key);
return ;
}
static void iniParse( const char * line, FILE * fpXML)
{
char writeBuffer[BUFFER_SIZE] = { 0 };
stateType state = getStateType( * line);
switch (state)
{
case STATE_COMMENT:
line ++ ;
sprintf(writeBuffer, " <!-- %s -->\n " , line);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
break ;
case STATE_SECTION:
line ++ ;
for ( int index = 0 ; index < BUFFER_SIZE && * line != ' \0 ' ; ++ line)
{
if ( * line != ' ] ' )
{
gSection[index ++ ] = * line;
}
else
{
gSection[index] = ' \0 ' ;
sprintf(writeBuffer, " <%s>\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
}
}
break ;
case STATE_SECTION_END:
if (gSectionIsEmpty() == FALSE)
{
sprintf(writeBuffer, " </%s>\n\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
memset(gSection, 0x00 , sizeof (gSection));
}
break ;
case STATE_KEY:
parse_key_and_value(line, writeBuffer);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
break ;
default :
break ;
}
return ;
}
static void createXML( const char * iniName, char * xml)
{
for ( int index = 0 ; index < 20 ; ++ index)
{
if (iniName[index] != ' . ' && iniName[index] != ' \0 ' )
{
xml[index] = iniName[index];
}
else
{
strcat(xml, " .xml " );
break ;
}
}
return ;
}
static void writeTheLastSectionEnd(FILE * fpXML)
{
char writeBuffer[BUFFER_SIZE] = { 0 };
sprintf(writeBuffer, " </%s>\n\n " , gSection);
fwrite(writeBuffer, strlen(writeBuffer), 1 , fpXML);
return ;
}
static void iniToxml( const char * iniName)
{
char xmlName[ 20 ] = { 0 };
createXML(iniName, xmlName);
FILE * fpINI = fopen(iniName, " r " );
FILE * fpXML = fopen(xmlName, " a+ " );
if (fpINI == NULL || fpXML == NULL)
{
fprintf(stderr, " open ini/xml file failed.\n " );
return ;
}
char line[BUFFER_SIZE] = { 0 };
while (fgets(line, BUFFER_SIZE, fpINI))
{
line[strlen(line) - 1 ] = ' \0 ' ;
iniParse(line, fpXML);
memset(line, 0x00 , sizeof (line) );
}
writeTheLastSectionEnd(fpXML);
fclose(fpINI);
fclose(fpXML);
return ;
}
int main( int argc, char * argv[])
{
if (argc < 2 )
{
fprintf(stdout, " usage: ./iniToxml <*.ini> (<*.ini>, ...) " );
return - 1 ;
}
for ( int i = 1 ; i < argc; ++ i)
{
iniToxml(argv[i]);
}
return 0 ;
}
;Configuration of http
[http]
domain = www.mysite.com
port = 8080
cgihome =/ cgi - bin
;Configuration of db
[database]
server = mysql
user = myname
password = toopendatabase
[http]
domain = www.mysite.com
port = 8080
cgihome =/ cgi - bin
;Configuration of db
[database]
server = mysql
user = myname
password = toopendatabase
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!--
Configuration of http
-->
< http >
< domain > www.mysite.com </ domain >
< port > 8080 </ port >
< cgihome >/ cgi - bin </ cgihome >
</ http >
<!-- Configuration of db -->
< database >
< server > mysql </ server >
< user > myname </ user >
< password > toopendatabase </ password >
</ database >
< http >
< domain > www.mysite.com </ domain >
< port > 8080 </ port >
< cgihome >/ cgi - bin </ cgihome >
</ http >
<!-- Configuration of db -->
< database >
< server > mysql </ server >
< user > myname </ user >
< password > toopendatabase </ password >
</ database >
END