KeyFile
Object Hierarchy:
Description:
[ Version ( since = "2.32" ) ]
[ CCode ( ref_function = "g_key_file_ref" , type_id = "G_TYPE_KEY_FILE" , unref_function = "g_key_file_unref" ) ]
public class KeyFile
`GKeyFile` parses .
ini-like config files.
`GKeyFile` lets you parse, edit or create files containing groups of key-value pairs, which we call "key files" for lack of a better name. Several freedesktop.org specifications use key files now, e.g the Desktop Entry Specification and the Icon Theme Specification .
The syntax of key files is described in detail in the Desktop Entry Specification, here is a quick summary: Key files consists of groups of key-value pairs, interspersed with comments.
```txt
this is just an example
there can be comments before the first group
[First Group]
Name=Key File Example\tthis value shows\nescaping
localized strings are stored in multiple key-value pairs
Welcome=Hello Welcome[de]=Hallo Welcome[fr_FR]=Bonjour Welcome[it]=Ciao
[Another Group]
Numbers=2;20;-200;0
Booleans=true;false;true;true ```
Lines beginning with a '#' and blank lines are considered comments.
Groups are started by a header line containing the group name enclosed in '[' and ']', and ended implicitly by the start of the next group or the end of the file. Each key-value pair must be contained in a group.
Key-value pairs generally have the form `key=value`, with the exception of localized strings, which have the form `key[locale]=value`, with a locale identifier of the form `lang_COUNTRY@MODIFIER` where `COUNTRY` and `MODIFIER` are optional. Space before and after the '=' character are ignored. Newline, tab, carriage return and backslash characters in value are escaped as `\n`, `\t`, `\r`, and `\\\\`, respectively. To preserve leading spaces in values, these can also be escaped as `\s`.
Key files can store strings (possibly with localized variants), integers, booleans and lists of these. Lists are separated by a separator character, typically ';' or ','. To use the list separator character in a value in a list, it has to be escaped by prefixing it with a backslash.
This syntax is obviously inspired by the .ini files commonly met on Windows, but there are some important differences:
- .ini files use the ';' character to begin comments, key files use the '#' character.
- Key files do not allow for ungrouped keys meaning only comments can precede the first group.
- Key files are always encoded in UTF-8.
- Key and Group names are case-sensitive. For example, a group called [GROUP] is a different from [group].
- .ini files don't have a strongly typed boolean entry type, they only have
GetProfileInt
. In key files, only true and false ( in lower case) are allowed.
Note that in contrast to the Desktop Entry Specification, groups in key files may contain the same key multiple times; the last entry wins. Key files may also contain multiple groups with the same name; they are merged together. Another difference is that keys and group names in key files are not restricted to ASCII characters.
Here is an example of loading a key file and reading a value:
```c g_autoptr(GError) error = NULL; g_autoptr(GKeyFile) key_file = g_key_file_new ();
if (!g_key_file_load_from_file (key_file, "key-file.ini", flags, &error)) { if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT )) g_warning ("Error loading key file: s", error->message); return; }
g_autofree gchar *val = g_key_file_get_string (key_file, "Group Name", "SomeKey", &error); if (val == NULL && !g_error_matches ( error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { g_warning ("Error finding key in key file: s", error->message); return; } else if (val == NULL) { // Fall back to a default value. val = g_strdup ("default-value"); } ```
Here is an example of creating and saving a key file:
```c g_autoptr(GKeyFile) key_file = g_key_file_new (); const gchar *val = …; g_autoptr(GError) error = NULL;
g_key_file_set_string (key_file, "Group Name", "SomeKey", val);
// Save as a file. if (!g_key_file_save_to_file (key_file, "key-file.ini", &error)) { g_warning ("Error saving key file: s", error->message); return; }
// Or store to a GBytes for use elsewhere. gsize data_len; g_autofree guint8 *data = (guint8 *) g_key_file_to_data (key_file, &data_len, &error); if (data == NULL) { g_warning ("Error saving key file: s", error->message); return; } g_autoptr(GBytes) bytes = g_bytes_new_take (g_steal_pointer (&data), data_len); ```
Example: KeyFile handling:
public static int main (string[] args) {
try {
//
// Read data:
//
KeyFile file = new KeyFile ();
// Use ',' as array-element-separator instead of ';'.
file.set_list_separator (',');
// file.load_from_file ("my-keyfile.conf", KeyFileFlags.NONE);
file.load_from_data ("""
# This is an example key-value file
[OptionalGroup]
required_key = myreq
optional_key = myopt
[BasicValues]
String=mystr
Bool=true
Int=300
Double=0.0
[Lists]
BoolArray=true,true,false
StringArray=Str1,Str2
[LocalizedString]
Hi=Hello
Hi[fr]=Bonjour
Hi[de]=Hallo
Hi[es]=Hola
""", -1, KeyFileFlags.NONE);
// ** BasicValues:
string @string = file.get_string ("BasicValues", "String");
bool @bool = file.get_boolean ("BasicValues", "Bool");
int @int = file.get_integer ("BasicValues", "Int");
double @double = file.get_double ("BasicValues", "Double");
// Output:
// ``mystr``
// ``true``
// ``300``
// ``0.000000``
print ("%s\n", @string);
print ("%s\n", @bool.to_string ());
print ("%d\n", @int);
print ("%f\n", @double);
// ** Lists:
bool[] bool_array = file.get_boolean_list ("Lists", "BoolArray");
string[] string_array = file.get_string_list ("Lists", "StringArray");
// Output: ``true true false``
foreach (bool b in bool_array) {
print ("%s ", b.to_string ());
}
print ("\n");
// Output: ``"Str1" "Str2"``
foreach (string str in string_array) {
print ("\"%s\" ", str);
}
print ("\n");
// ** LocalizedString:
string hi = file.get_locale_string ("LocalizedString", "Hi", null);
// Output: ``Hello``
print ("%s\n", hi);
// ** OptionalGroup
// Check availability before accessing to avoid exceptions:
if (file.has_group ("OptionalGroup")) {
string required_key = file.get_string ("OptionalGroup", "required_key");
string? optional_key = null;
if (file.has_key ("OptionalGroup", "optional_key")) {
optional_key = file.get_string ("OptionalGroup", "optional_key");
}
// Output:
// ``myreq``
// ``myopt``
print ("%s\n", required_key);
print ("%s\n", optional_key);
}
//
// Modify data:
//
file.set_string ("BasicValues", "String", "my-new-value");
file.remove_group ("LocalizedString");
file.remove_group ("OptionalGroup");
file.remove_key ("Lists", "StringArray");
//
// List all groups & keys:
//
// Output:
// ``Key: BasicValues.String = my-new-value``
// ``Key: BasicValues.Bool = true``
// ``Key: BasicValues.Int = 300``
// ``Key: BasicValues.Double = 0.0``
// ``Key: Lists.BoolArray = true,true,false``
foreach (unowned string group in file.get_groups ()) {
foreach (unowned string key in file.get_keys (group)) {
print ("Key: %s.%s = %s\n", group, key, file.get_value (group, key));
}
}
//
// Print the modified keyfile to stdout:
//
// Output:
// ``-----``
// ``[BasicValues]``
// ``String=my-new-value``
// ``Bool=true``
// ``Int=300``
// ``Double=0.0``
// ````
// ``[Lists]``
// ``BoolArray=true,true,false``
// ``----``
string keyfile_str = file.to_data ();
print ("-----\n%s----\n", keyfile_str);
} catch (KeyFileError e) {
print ("Error: %s\n", e.message);
}
return 0;
}
valac --pkg glib-2.0 GLib.KeyFile.vala