Мне нужно читать/писать в файл INI на C. Для меня немного странно, что я не могу найти какой-либо стандартный способ сделать это. Каков общий способ работы с файлами INI в C?
Я предпочитаю как платформенно-независимые библиотеки, так и библиотеки синтаксического анализатора файлов INI Linux.
Это ссылка может пролить свет на этот вопрос (написана автором inih, о чем упоминал Загорулкин Дмитрий) — Я использовал minIni и остался доволен этим ..
Я знаю об этой библиотеке. Вы можете использовать ее http://code.google.com/p/inih/
2
/inih
inih (INI не изобретен здесь) — это простой синтаксический анализатор файлов .INI, написанный на C. Это всего лишь пара страниц кода, и он был разработан для маленький и простой , поэтому он подходит для встраиваемых систем. Он также более или менее совместим со стилем Python ConfigParser для файлов .INI, включая многострочный синтаксис в стиле RFC 822 и записи name: value
.
Для использования просто дайте ini_parse ()
INI-файл, и он будет вызывать обратный вызов для каждой проанализированной пары name = value
, давая вам строки для раздела, имя и значение. Это делается таким образом («стиль SAX»), потому что он хорошо работает во встроенных системах с низким объемом памяти, а также потому, что он подходит для реализации KISS.
Вы также можете вызвать ini_parse_file ()
для анализа непосредственно из объекта FILE *
, ini_parse_string ()
для анализа данных из строки или ini_parse_stream ()
для синтаксического анализа с использованием пользовательской функции чтения в стиле fgets для пользовательского ввода-вывода.
Загрузите выпуск, просмотрите исходный код или прочитайте, как использовать inih в стиле DRY с X-макросами.
Параметры времени компиляции
Вы можете управлять различными аспектами inih с помощью определений препроцессора:
Параметры синтаксиса
- Многострочные записи: По умолчанию inih поддерживает многострочные записи в стиле Python ConfigParser. Чтобы отключить, добавьте
-DINI_ALLOW_MULTILINE = 0
. - Спецификация UTF-8: По умолчанию inih разрешает UTF-8 Последовательность спецификации (0xEF 0xBB 0xBF) в начале файлов INI. Чтобы отключить, добавьте
-DINI_ALLOW_BOM = 0
. - Встроенные комментарии: По умолчанию inih разрешает встроенные комментарии с
;
символ. Чтобы отключить, добавьте-DINI_ALLOW_INLINE_COMMENTS = 0
. Вы также можете указать, какой символ (символы) запускает встроенный комментарий, используяINI_INLINE_COMMENT_PREFIXES
. - Комментарии в начале строки: По умолчанию inih позволяет как
;
, так и#
начинать комментарий в начале строки. Вы можете изменить это, изменивINI_START_COMMENT_PREFIXES
. - Разрешить без значения: по умолчанию inih обрабатывает имя без значения (без
=
или:
в строке) как ошибку. Чтобы разрешить имена без значений, добавьте-DINI_ALLOW_NO_VALUE = 1
, и inih вызовет вашу функцию-обработчик со значением NULL.
Параметры синтаксического анализа
- Остановить при первой ошибке: по умолчанию inih продолжает синтаксический анализ остальной части файла после ошибки. Чтобы остановить анализ при первой ошибке, добавьте
-DINI_STOP_ON_FIRST_ERROR = 1
. - Номера строк отчета: по умолчанию
ini_handler
обратный вызов не получает номер строки в качестве параметра. Если вам это нужно, добавьте-DINI_HANDLER_LINENO = 1
. - Обработчик вызовов в новом разделе: По умолчанию inih вызывает только обработчик для каждой пары
name = value
. Чтобы обнаружить новые разделы (например, в файле INI есть несколько разделов с одинаковыми именами), добавьте-DINI_CALL_HANDLER_ON_NEW_SECTION = 1
. Затем ваша функция-обработчик будет вызываться каждый раз, когда будет обнаружен новый раздел, сsection
, установленным на новое имя раздела, ноname
и значение
Параметры памяти
- Стек против кучи: По умолчанию inih создает в стеке строчный буфер фиксированного размера. Чтобы выделить в куче с помощью
malloc
, укажите-DINI_USE_STACK = 0
. - Максимальная длина строки : Максимальная длина строки по умолчанию (для стека или кучи) составляет 200 байт. Чтобы изменить это, добавьте что-то вроде
-DINI_MAX_LINE = 1000
. Обратите внимание, чтоINI_MAX_LINE
должен быть на 3 больше, чем самая длинная строка (из-заr
,n
и NUL ). - Начальный размер malloc:
INI_INITIAL_ALLOC
указывает начальный размер malloc при использовании кучи. По умолчанию 200 байт. - Разрешить перераспределение: по умолчанию при использовании кучи (
-DINI_USE_STACK = 0
) inih выделяет буфер фиксированного размера вINI_INITIAL_ALLOC
байтах. Чтобы позволить этому возрасту доINI_MAX_LINE
байтов, удваивая при необходимости, установите-DINI_ALLOW_REALLOC = 1
. - Пользовательский распределитель: по умолчанию при использовании кучи стандартные библиотеки
malloc
,free
иrealloc
используются функции; чтобы использовать настраиваемый распределитель, укажите-DINI_CUSTOM_ALLOCATOR = 1
(и-DINI_USE_STACK = 0
). Вы должны определить и связать функции с именамиini_malloc
,ini_free
и (если установленINI_ALLOW_REALLOC
)ini_realloc
, который должен иметь такие же подписи, что и функции выделения памятиstdlib.h
.
Простой пример на C
#include #include #include #include "../ini.h"typedef struct {int version; const char * name; const char * email;} конфигурация; статический обработчик int (void * user, const char * section, const char * name, const char * value) {configuration * pconfig = (конфигурация *) пользователь; #define MATCH (s, n) strcmp (section, s) == 0 && strcmp (name, n) == 0 if (MATCH ("протокол", "версия")) {pconfig -> version = atoi (значение);} else if (MATCH ("user", "name")) {pconfig-> name = strdup (value);} else if (MATCH ("user", "email")) {pconfig-> email = strdup (value);} else {return 0;/* неизвестный раздел/имя, ошибка */} return 1;} int main (int argc, char * argv []) {конфигурационная конфигурация; if ( ini_parse ("test.ini", обработчик, & config)
Пример C ++
Если вы знакомы с C ++ и STL, существует также простой в использовании класс INIReader, который хранит значения в карте
и позволяет Get ()
их:
#include #include "INIReader.h" int main () {INIReader читатель ("../examples/test.ini"); if (reader.ParseError ()
Этот простой API C ++ работает нормально, но не очень полноценный. Я не планирую больше работать над C ++ API в данный момент, поэтому, если вам нужно немного больше возможностей (например, GetSections ()
и GetFields ()
functions), посмотрите эти форки:
- https://github.com/Blandinium/inih
- https://github.com /OSSystems/inih
Отличия от ConfigParser
Некоторые различия между inih и модулем стандартной библиотеки Python ConfigParser:
- Пары INI name = value, указанные выше любых заголовков разделов, рассматриваются как допустимые элементы без раздела (имя раздела — пустая строка). В ConfigParser отсутствие раздела является ошибкой.
- Продолжение строк обрабатывается с ведущими пробелами в продолжающихся строках (например, ConfigParser). Однако вместо того, чтобы объединять продолженные строки вместе, они обрабатываются как отдельные значения для одного и того же ключа (в отличие от ConfigParser)..
Примечания к платформе
- Windows/Win32 изначально использует имена файлов UTF-16, поэтому для обработки путей Unicode вам необходимо вызвать
_wfopen ()
, чтобы открыть файл, а затемini_parse_file ()
для его анализа; inih не включаетwchar_t
или обработку Unicode.
Примечания к Meson
- meson.build не требуется для использования или компиляции inih, его основное назначение — для дистрибутивов.
- По умолчанию Meson настроен для установки дистрибутива, но такое поведение может быть настроенным для встроенных вариантов использования:
- с
-Ddefault_library = static
создаются статические библиотеки. - с
-Ddistro_install = false
библиотеки, заголовки и файлы pkg-config не будут установлены. - с помощью
-Dwith_INIReader = false
вы можете отключить сборку библиотеку C ++.
- с
- Все параметры времени компиляции также реализованы в Meson, их определение можно найти в файле meson_options.txt. Они не будут работать, если для
distro_install
установлено значениеtrue
. - Если вы хотите использовать inih для программ, которые могут быть поставляется в дистрибутиве, рассмотрите возможность компоновки с общими библиотеками. Записи pkg-config:
inih
иINIReader
. - Если вы используете inih как подпроект Meson, вы можете использовать переменные зависимостей
inih_dep
иINIReader_dep
. Возможно, вы захотите установить для подпроектаdefault_library = static
иdistro_install = false
. Официальная оболочка предоставляется на WrapDB. - Для упаковщиков: если вы хотите пометить версию в файле pkg-config, вам нужно будет сделать это ниже по течению. Добавьте
version: '',
после тегаlicense
в функциюproject ()
иversion: meson.project_version (),
после тегаsoversion
в обеих функцияхlibrary ()
.
Сборка из vcpkg
Вы можете собрать и установить inih с помощью диспетчера зависимостей vcpkg:
git clone https://github .com/Microsoft/vcpkg.gitcd vcpkg./bootstrap-vcpkg.sh./vcpkg Integrate install./vcpkg install inih
Порт inih в vcpkg обновляется Члены группы Майкрософт и участники сообщества. Если версия устарела, создайте проблему или запрос на вытягивание в репозитории vcpkg.
Ссылки по теме
- Пакет Conan для inih (Conan — менеджер пакетов C/C ++)