# Reading/Writing .ini–Style Files Control

toolslib\toolbox\inifile.fp

This instrument driver contains functions for storing and accessing hierarchical configuration information using .ini–style files or Windows Registry Keys.

To increase speed, this instrument driver has not been implemented with any multithread–safe locking. National Instruments recommends that you do not share access to the same .ini file among multiple threads. You can have multiple .ini files coexisting with multiple threads, as long has no single .ini file is shared among multiple threads.

.ini–style files have the following format:

[section 1]
tag 1 = "string value 1"
tag 2 = "string value 2"
tag 3 = 53

[section 2]
tag 1 = True
tag 2 = –12.3

where section 1, section 2, tag 1, tag 2, and tag 3 are user–defined names. The number of sections and tags is unlimited.

The Windows Registry has the following format:

Root Key

SubKey 1

Value Name 1 Value Data

SubKey 2

Value Name 2 Value Data

where "SubKey 1", "SubKey 2", "Value Name 1", and "Value Name 2" are user–defined names, but "Root Key" is one of a number of system–defined values.

This instrument driver helps you access, store, and manipulate Sections of configuration information, each containing tag/value pairs. For .ini files, Sections correspond to bracketed entries in the file, where each Section usually groups logically a number of tag=value entries (tag/value pairs).

For Windows Registry branches, contain all configuration information for an application in a branch starting at a user–defined Base Key that descends from one of the system–defined Root Keys. Each SubKey under the Base Key corresponds to a Section, where each value–name/value–data pair under that Key is considered a tag/value pair.

This instrument driver supports the following logical value types:

- strings
- integers
- unsigned integers
- doubles
- boolean

Strings can be of unlimited size. If strings in a .ini–style file are more than 80 characters in length, they are broken into multiple lines. Each line has a tag suffix, which the following example demonstrates:

[section 1]
tag 1 line 0001 = "This is the first line of a very long "
tag 1 line 0002 = "paragraph. This is the second line."

Unprintable characters are written using hexadecimal escape codes.

For Windows Registry storage, all data is actually string data. Your application is free to interpret the data in any supported format.

For writing this type of configuration information to the system, the general approach is to build up the tag/value pairs in memory and then to write the entire file or Registry branch at once. For reading, the general approach is to read the entire file or Key branch into memory at once and then to interrogate individual tag/value pairs.

To write a file with two sections, each containing two tags, the code without error checking might look similar to the following code:

IniText iniText;
char pathName[MAX_PATHNAME_LEN];
char dirName[MAX_PATHNAME_LEN];
/* set up the pathName for the .ini file */
GetProjectDir (dirName);
MakePathname (dirName, "myconfig.ini", pathName);
/* create object for holding the value/tag pairs */
iniText = Ini_New (TRUE); /* TRUE for automatic sorting */
/* create the in–memory tag/value pairs */
Ini_PutString (iniText, "section 1", "tag 1", "string 1");
Ini_PutString (iniText, "section 1", "tag 2", "string 2");
Ini_PutInt (iniText, "section 2", "tag 1", 53);
Ini_PutBoolean (iniText, "section 2", "tag 2", TRUE);
/* write out the tag/value pairs */
Ini_WriteToFile (iniText, pathName);
/* dispose of the in–memory tag/value pairs */
Ini_Dispose (iniText);

To read the same file, the code without error checking might look similar to the following code:

IniText iniText;
char pathName[MAX_PATHNAME_LEN];
char dirName[MAX_PATHNAME_LEN];
char *str1, *str2;
int intVal, boolVal;
/* set up the pathName for the .ini file */
GetProjectDir (dirName);
MakePathname (dirName, "myconfig.ini", pathName);
/* create object for holding the value/tag pairs */
iniText = Ini_New (TRUE); /* TRUE for automatic sorting */
/* read in the tag/value pairs */
Ini_ReadFromFile (iniText, pathName);
/* create the in–memory tag/value pairs */
Ini_GetStringCopy (iniText, "section 1", "tag 1", &str1);
Ini_GetStringCopy (iniText, "section 1", "tag 2", &str2);
Ini_GetInt (iniText, "section 2", "tag 1", &intVal);
Ini_GetBoolean (iniText, "section 2", "tag 2", &boolVal);
/* dispose of the in–memory tag/value pairs */
Ini_Dispose (iniText);

You gain the following advantages by storing information in this type of standard fashion.

- Humans can read, and potentially edit, the files and Keys.
- Adding new information to the file does not change its format. This makes backwards compatibility virtually automatic.
- Multiple independent modules or programs can use the same file, as long as each module or program uses unique section names.
- Storing information in this way is platform–independent, which means there are no byte–packing, alignment, OS–dependence, or endianization issues.

The disadvantage of storing information in this fashion is that binary format has the maximum potential for size and speed optimization.

While it may seem that the section/item organization of this type of storage limits the data to two levels of hierarchy, it is possible to obtain multiple levels of hierarchy by adding a prefix for each level of hierarchy to the section names.

| Note This instrument driver makes extensive use of dynamic memory and therefore runs much slower if the project's debugging level is set to extended. Set the debugging level in the Build Options dialog box, which you can access by selecting Options»Build Options.