首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言文本處理三大格式完全解析:INI/Conf、XML 與 YAML 庫選型與實戰

     編輯:關於C語言

一、INI / Conf 格式:簡單鍵值對

結構:[section] + key=value,適合簡單配置。

推薦庫

  • inih (ini.h):單頭檔、ANSI C、< 2KB、支援多行、註解、大小寫不敏感。
    https://github.com/benhoyt/inih
  • libconfini:輕量、支援型別轉換、區段巢狀。
  • GKeyFile (GLib):跨平台、完整 INI 規範、需 GLib 依賴。

inih 使用範例

// config.ini
[server]
port = 8080
host = "0.0.0.0"
[database]
url = "postgres://user:pass@localhost/db"

#define INI_MAX_LINE 200
#include "ini.h"

typedef struct { int port; const char *host; const char *db_url; } Config;

int handler(void *user, const char *section, const char *name, const char *value) {
    Config *c = (Config*)user;
    if (strcmp(section, "server") == 0) {
        if (strcmp(name, "port") == 0) c->port = atoi(value);
        else if (strcmp(name, "host") == 0) c->host = strdup(value);
    } else if (strcmp(section, "database") == 0) {
        if (strcmp(name, "url") == 0) c->db_url = strdup(value);
    }
    return 1;
}

int main() {
    Config cfg = {0};
    if (ini_parse("config.ini", handler, &cfg) < 0) {
        fprintf(stderr, "Parse failed\n");
        return 1;
    }
    printf("Port: %d, Host: %s, DB: %s\n", cfg.port, cfg.host, cfg.db_url);
    return 0;
}

二、XML 格式:結構化、命名空間、Schema 驗證

適合複雜文檔、資料交換、文書標記。

推薦庫

  • libxml2:工業標準、DOM/SAX/Reader 多種 API、XPath、XSLT、Schema 驗證、Python 綁定。
    apt-get install libxml2-dev / yum install libxml2-devel
  • expat:SAX 事件流、極輕量、無 DOM、適合嵌入式/串流解析。
  • mxml (Mini-XML):單檔、輕量 DOM、適合小型專案。

libxml2 DOM 解析範例

#include 
#include 
#include 

int main() {
    xmlDoc *doc = xmlReadFile("data.xml", NULL, 0);
    if (!doc) return 1;
    
    xmlNode *root = xmlDocGetRootElement(doc);
    for (xmlNode *cur = root->children; cur; cur = cur->next) {
        if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (xmlChar*)"item") == 0) {
            xmlChar *name = xmlGetProp(cur, (xmlChar*)"name");
            xmlChar *content = xmlNodeGetContent(cur);
            printf("Item: %s = %s\n", name, content);
            xmlFree(name); xmlFree(content);
        }
    }
    xmlFreeDoc(doc);
    xmlCleanupParser();
    return 0;
}

SAX 事件流 (大檔案/低記憶體)

static void startElement(void *ctx, const xmlChar *name, const xmlChar **atts) {
    if (xmlStrcmp(name, (xmlChar*)"item") == 0) {
        for (int i = 0; atts[i]; i += 2)
            printf("  %s='%s'", atts[i], atts[i+1]);
        puts("");
    }
}

int main() {
    xmlSAXHandler sax = {0};
    sax.startElement = startElement;
    xmlSAXUserParseFile(&sax, NULL, "large.xml");
    xmlCleanupParser();
    return 0;
}

三、YAML 格式:人類可讀、豐富型別、錨點引用

適合複雜配置、CI/CD 流程定義 (GitHub Actions, GitLab CI)、Kubernetes 資源清單。

推薦庫

  • libyaml:官方 C 實現、事件流 API (類 SAX)、支援 1.1/1.2 規範。
    apt-get install libyaml-dev
  • yaml-cpp:C++ 封裝、DOM 風格、易用性極佳 (需 C++ 專案)。

libyaml 事件解析範例

#include 
#include 
#include 

int main() {
    FILE *fh = fopen("config.yaml", "r");
    yaml_parser_t parser;
    yaml_event_t event;
    
    yaml_parser_initialize(&parser);
    yaml_parser_set_input_file(&parser, fh);
    
    while (yaml_parser_parse(&parser, &event)) {
        switch (event.type) {
            case YAML_SCALAR_EVENT:
                printf("Scalar: %s\n", event.data.scalar.value);
                break;
            case YAML_MAPPING_START_EVENT:
                puts("Mapping start");
                break;
            case YAML_SEQUENCE_START_EVENT:
                puts("Sequence start");
                break;
            default: break;
        }
        yaml_event_delete(&event);
    }
    
    yaml_parser_delete(&parser);
    fclose(fh);
    return 0;
}

四、選型決策矩陣

需求推薦格式推薦庫
極簡配置、嵌入式、零依賴INIinih (單頭檔)
結構化資料、需 Schema 驗證、XPath 查詢XMLlibxml2 (完整功能) / expat (串流)
人類可讀配置、巢狀結構、CI/CD、K8sYAMLlibyaml (C) / yaml-cpp (C++)
高效能序列化、二進位、跨語言Protobuf/MessagePackprotobuf-c / msgpack-c
記憶體極受限、單向解析XML/JSONexpat / jsmn (JSON)

五、常見坑與避坑

  1. XML 實體展開攻擊 (XXE):libxml2 預設展開外部實體,解析不可信輸入前必須 xmlSetExternalEntityLoader(NULL) 或 XML_PARSE_NOENT 關閉。
  2. YAML 錨點/別名導致無限遞迴:解析器需設定深度限制。
  3. INI 重複 key 行為未定義:inih 最後一個生效,文件化約定。
  4. 編碼問題:XML 預設 UTF-8,讀取 GBK/Big5 檔需先轉碼 (libiconv)。
  5. 大檔案記憶體爆炸:DOM 解析全載入記憶體,>100MB 改用 SAX/Reader/事件流。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved