Tom 发表于 2009-4-25 20:04:57

【转】Gtk+读写ini文件

文章转载自:http://blog.chinaunix.net/u/19671/showart.php?id=117843
以下两个文件cfgfile.h和cfgfile.c实现了在gtk应用程序中读写ini文件的方法,现贴上源代码,以供参考。
源文件cfgfile.h

#ifndef __CFG_FILE_H__
#define __CFG_FILE_H__

#include <glib.h>
#include <gtk/gtk.h>
#include <time.h>

typedef struct{
        gchar *key;
        gchar *value;
}ConfigLine;

typedef struct{
        gchar *name;
        GList *lines;
}ConfigSection;

typedef struct{
        GList *sections;
        gchar *cfgfilename;
        gboolean changed;
}ConfigFile;

ConfigFile *cfg_file_new (void);
ConfigFile *cfg_file_open_file (gchar * filename);
gboolean    cfg_file_write_file (ConfigFile * cfg, gchar * filename);
void      cfg_file_free (ConfigFile * cfg);

gboolean cfg_file_read_string (ConfigFile * cfg, gchar * section,gchar * key, gchar ** value);
gboolean cfg_file_read_int (ConfigFile * cfg, gchar * section,gchar * key, gint * value);
gboolean cfg_file_read_long (ConfigFile * cfg, gchar * section,gchar * key, glong * value);
gboolean cfg_file_read_time (ConfigFile * cfg, gchar * section,gchar * key, time_t * value);
gboolean cfg_file_read_boolean (ConfigFile * cfg, gchar * section,gchar * key, gboolean * value);
gboolean cfg_file_read_color (ConfigFile * cfg, gchar * section, gchar * key,GdkColor *color);

void cfg_file_write_string (ConfigFile * cfg, gchar * section,gchar * key, gchar * value);
void cfg_file_write_int (ConfigFile * cfg, gchar * section, gchar * key,gint value);
void cfg_file_write_long (ConfigFile * cfg, gchar * section, gchar * key,glong value);
void cfg_file_write_time (ConfigFile * cfg, gchar * section,gchar * key, time_t value);
void cfg_file_write_boolean (ConfigFile * cfg, gchar * section,gchar * key, gboolean value);
void cfg_file_write_color (ConfigFile * cfg, gchar * section, gchar * key,GdkColor color);

void cfg_file_rename_section (ConfigFile * cfg, gchar * section,gchar * section_name);
void cfg_file_remove_key (ConfigFile * cfg, gchar * section,gchar * key);
void cfg_file_remove_section (ConfigFile * cfg, gchar * section);

#endif



源文件cfgfile.c

/*
this file is copy form x11amp,i changed it for some place.
这个文件是我从x11amp(现在叫xmms)拷来的,增删了几个函数.
*/


#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "cfgfile.h"

static ConfigSection *cfg_file_create_section (ConfigFile * cfg, gchar * name);
static ConfigLine    *cfg_file_create_string (ConfigSection * section, gchar * key,gchar * value);
static ConfigSection *cfg_file_find_section (ConfigFile * cfg, gchar * name);
static ConfigLine    *cfg_file_find_string (ConfigSection * section, gchar * key);

ConfigFile* cfg_file_new (void)
{
        ConfigFile *cfg;

        cfg = (ConfigFile *)g_malloc0 (sizeof (ConfigFile));

        return cfg;
}

ConfigFile* cfg_file_open_file (gchar * filename)
{
        ConfigFile *cfg;

        FILE *file;
        gchar *buffer, **lines, *tmp;
        gint i;
        struct stat stats;
        ConfigSection *section = NULL;

        if (stat (filename, &stats) == -1)
                return NULL;
        if (!(file = fopen (filename, "rb")))
                return NULL;

        buffer = (gchar *)g_malloc (stats.st_size + 1);
        fread (buffer, 1, stats.st_size, file);
/*        if (fread (buffer, 1, stats.st_size, file) != stats.st_size)
        {
                g_free (buffer);
                fclose (file);
                return NULL;
        }
*/
        fclose (file);
        buffer = '\0';

        cfg = (ConfigFile *)g_malloc0 (sizeof (ConfigFile));
        cfg->cfgfilename = g_strdup (filename);
        cfg->changed = 0;
        lines = g_strsplit (buffer, "\n", 0);
        g_free (buffer);
        i = 0;
        while (lines)
        {
                if (lines == '[')
                {
                        if ((tmp = strchr (lines, ']')))
                        {
                                *tmp = '\0';
                                section =
                                        cfg_file_create_section (cfg,
                                                             &lines);
                        }
                }
                else if (lines != '#' && section)
                {
                        if ((tmp = strchr (lines, '=')))
                        {
                                *tmp = '\0';
                                tmp++;
                                cfg_file_create_string (section, lines, tmp);
                        }
                }
                i++;
        }
        g_strfreev (lines);
        return cfg;
}


gboolean cfg_file_write_file (ConfigFile * cfg, gchar * filename)
{
        FILE *file;
        GList *section_list, *line_list;
        ConfigSection *section;
        ConfigLine *line;

        if (!(file = fopen (filename, "wb")))
                return FALSE;

        section_list = cfg->sections;
        while (section_list)
        {
                section = (ConfigSection *) section_list->data;
                if (section->lines)
                {
                        fprintf (file, "[%s]\n", section->name);
                        line_list = section->lines;
                        while (line_list)
                        {
                                line = (ConfigLine *) line_list->data;
                                fprintf (file, "%s=%s\n", line->key,
                                       line->value);
                                line_list = g_list_next (line_list);
                        }
                        fprintf (file, "\n");
                }
                section_list = g_list_next (section_list);
        }
        fclose (file);
        return TRUE;
}

gboolean cfg_file_read_string (ConfigFile * cfg, gchar * section, gchar * key,gchar ** value)
{
        ConfigSection *sect;
        ConfigLine *line;

        *value = NULL;
        if (!(sect = cfg_file_find_section (cfg, section)))
                return FALSE;
        if (!(line = cfg_file_find_string (sect, key)))
                return FALSE;
        *value = g_strdup (line->value);
        return TRUE;
}

gboolean cfg_file_read_int (ConfigFile * cfg, gchar * section, gchar * key, gint * value)
{
        gchar *str;

        if (!cfg_file_read_string (cfg, section, key, &str))
        {
                *value = 0;
                return FALSE;
        }
        *value = atoi (str);
        g_free (str);

        return TRUE;
}

gboolean cfg_file_read_long (ConfigFile * cfg, gchar * section, gchar * key, glong * value)
{
        gchar *str;

        if (!cfg_file_read_string (cfg, section, key, &str))
        {
                *value = 0;
                return FALSE;
        }
        *value = atol (str);
        g_free (str);

        return TRUE;
}

gboolean cfg_file_read_time (ConfigFile * cfg, gchar * section, gchar * key,time_t * value)
{
        gchar *str;

        if (!cfg_file_read_string (cfg, section, key, &str))
        {
                *value = 0;
                return FALSE;
        }
        *value = atol (str);
        g_free (str);

        return TRUE;
}

gboolean cfg_file_read_boolean (ConfigFile * cfg, gchar * section, gchar * key,gboolean * value)
{
        gchar *str;

        if (!cfg_file_read_string (cfg, section, key, &str))
        {
                *value = FALSE;
                return FALSE;
        }
        if (!strcmp (str, "0"))
                *value = FALSE;
        else
                *value = TRUE;        //gtk_widget_modify_base(sd->mainwin->textview,GTK_STATE_NORMAL,&sd->conf.bgcolor);

        g_free (str);
        return TRUE;
}

gboolean cfg_file_read_color (ConfigFile * cfg, gchar * section, gchar * key,GdkColor *color)
/*this was added by yetist */
{
        gchar *str;
        gchar *p;
        gchar *canshu;
        gchar *string;
        gint i=0;
        if (!cfg_file_read_string (cfg, section, key, &str))
        {
                color->pixel=0;
                color->red=0;
                color->green=0;
                color->blue=0;
                return FALSE;
        }       
        strcpy(string,str);
        canshu=strtok(string,":");
        while((p=strtok(NULL,":")))
        { i++;canshu=p; }
        color->red=atol(canshu);
        color->green=atol(canshu);
        color->blue=atol(canshu);
        return TRUE;
}

void cfg_file_write_string (ConfigFile * cfg, gchar * section, gchar * key,gchar * value)
{
        ConfigSection *sect;
        ConfigLine *line;

        cfg->changed = 1;
        sect = cfg_file_find_section (cfg, section);
        if (!sect)
                sect = cfg_file_create_section (cfg, section);
        if ((line = cfg_file_find_string (sect, key)))
        {
                g_free (line->value);
                line->value = g_strchug (g_strchomp (g_strdup (value)));
        }
        else
                cfg_file_create_string (sect, key, value);
}

void cfg_file_write_int (ConfigFile * cfg, gchar * section, gchar * key, gint value)
{
        gchar *strvalue;
        strvalue = g_strdup_printf ("%d", value);
        cfg_file_write_string (cfg, section, key, strvalue);
        g_free (strvalue);
}

void cfg_file_write_long (ConfigFile * cfg, gchar * section, gchar * key, glong value)
{
        gchar *strvalue;
        strvalue = g_strdup_printf ("%ld", value);
        cfg_file_write_string (cfg, section, key, strvalue);
        g_free (strvalue);
}

void cfg_file_write_time (ConfigFile * cfg, gchar * section, gchar * key,time_t value)
{
        gchar *strvalue;
        strvalue = g_strdup_printf ("%ld", value);
        cfg_file_write_string (cfg, section, key, strvalue);
        g_free (strvalue);
}

void cfg_file_write_boolean (ConfigFile * cfg, gchar * section, gchar * key,gboolean value)
{
        if (value)
                cfg_file_write_string (cfg, section, key, "1");
        else
                cfg_file_write_string (cfg, section, key, "0");
}

void cfg_file_write_color (ConfigFile * cfg, gchar * section, gchar * key,GdkColor color)
/*this was added by yetist */
{
        gchar *strvalue;
        strvalue = g_strdup_printf ("%u:%u:%u", color.red, color.green, color.blue);
        cfg_file_write_string (cfg, section, key, strvalue);
        g_free (strvalue);
}





void cfg_file_rename_section (ConfigFile * cfg, gchar * section,gchar * section_name)
{
        ConfigSection *sect;

        sect = cfg_file_find_section (cfg, section);
        if (sect)
        {
                cfg->changed = 1;
                g_free (sect->name);
                sect->name = g_strdup (section_name);
        }
}

void cfg_file_remove_key (ConfigFile * cfg, gchar * section, gchar * key)
{
        ConfigSection *sect;
        ConfigLine *line;

        sect = cfg_file_find_section (cfg, section);
        if (sect)
        {
                line = cfg_file_find_string (sect, key);
                if (line)
                {
                        cfg->changed = 1;
                        g_free (line->key);
                        g_free (line->value);
                        g_free (line);
                        sect->lines = g_list_remove (sect->lines, line);
                }
        }
}

void cfg_file_remove_section (ConfigFile * cfg, gchar * section)        /* this was added by me 我加的,应该没错误 */
{
        ConfigSection *sect;
        ConfigLine *line;
        GList *line_list;

        sect = cfg_file_find_section (cfg, section);
        if (sect)
        {
                cfg->changed = 1;
                g_free (sect->name);
                line_list = sect->lines;
                while (line_list)
                {
                        line = (ConfigLine *) line_list->data;
                        g_free (line->key);
                        g_free (line->value);
                        g_free (line);
                        line_list = g_list_next (line_list);
                }
                g_list_free (sect->lines);
                g_free (sect);
                cfg->sections = g_list_remove (cfg->sections, sect);
        }
}


void cfg_file_free (ConfigFile * cfg)
{
        ConfigSection *section;
        ConfigLine *line;
        GList *section_list, *line_list;

        g_free (cfg->cfgfilename);
        section_list = cfg->sections;
        while (section_list)
        {
                section = (ConfigSection *) section_list->data;
                g_free (section->name);

                line_list = section->lines;
                while (line_list)
                {
                        line = (ConfigLine *) line_list->data;
                        g_free (line->key);
                        g_free (line->value);
                        g_free (line);
                        line_list = g_list_next (line_list);
                }
                g_list_free (section->lines);
                g_free (section);

                section_list = g_list_next (section_list);
        }
        g_list_free (cfg->sections);
        cfg->sections = NULL;        /*这两行我加的,cfg_file_free后可回到cfg_file_new状态,可继续使用. */
        cfg->cfgfilename = NULL;
}

static ConfigSection * cfg_file_create_section (ConfigFile * cfg, gchar * name)
{
        ConfigSection *section;
        section = (ConfigSection *)g_malloc0 (sizeof (ConfigSection));
        section->name = g_strdup (name);
        cfg->sections = g_list_append (cfg->sections, section);

        return section;
}

static ConfigLine * cfg_file_create_string (ConfigSection * section, gchar * key, gchar * value)
{
        ConfigLine *line;
        line = (ConfigLine *)g_malloc0 (sizeof (ConfigLine));
        line->key = g_strchug (g_strchomp (g_strdup (key)));
        line->value = g_strchug (g_strchomp (g_strdup (value)));
        section->lines = g_list_append (section->lines, line);

        return line;
}

static ConfigSection * cfg_file_find_section (ConfigFile * cfg, gchar * name)
{
        ConfigSection *section;
        GList *list;

        list = cfg->sections;
        while (list)
        {
                section = (ConfigSection *) list->data;
                if (!strcasecmp (section->name, name))
                        return section;
                list = g_list_next (list);
        }
        return NULL;
}

static ConfigLine * cfg_file_find_string (ConfigSection * section, gchar * key)
{
        ConfigLine *line;
        GList *list;

        list = section->lines;
        while (list)
        {
                line = (ConfigLine *) list->data;
                if (!strcasecmp (line->key, key))
                        return line;
                list = g_list_next (list);
        }
        return NULL;
}


用法示例(main.c):

#include <gtk/gtk.h>
#include "cfgfile.h"

void on_button_clicked(GtkButton *button,gpointer data)
{
        ConfigFile *ini;
        ini=cfg_file_new();
        cfg_file_write_string(ini,"system","gtk+","2.9");
        cfg_file_write_int(ini,"system","NO.",89);
        cfg_file_write_boolean(ini,"system","reg","TRUE");
        cfg_file_write_string(ini,"about","soft","for you");
        cfg_file_write_file(ini,"test.ini");
        cfg_file_free(ini);
}

int main(int argc,char* argv[])
{
        GtkWidget *window;
        GtkWidget *button;
        gtk_init(&argc,&argv);
        window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(gtk_main_quit),NULL);
        gtk_window_set_title(GTK_WINDOW(window),"use ini file");
        gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
        gtk_container_set_border_width(GTK_CONTAINER(window),20);
        button=gtk_button_new_with_label("click me");
        g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(on_button_clicked),NULL);
        gtk_container_add(GTK_CONTAINER(window),button);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}



test.ini文件内容:


gtk+=2.9
NO.=89
reg=1


soft=for you


注意:如果ini文件为GB2312编码,那么读取到的字符串将为乱码,请使用g_locale_to_utf8(string,-1,NULL,NULL,NULL);转换就可以了。
      当然要保存字符串,请使用g_locale_from_utf8(string,-1,NULL,NULL,NULL);

heiher 发表于 2010-10-21 06:26:00

GKeyFile 不就是干这个的吗?为何又要自己实现一个?
页: [1]
查看完整版本: 【转】Gtk+读写ini文件