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

C 語言字符編碼轉換實戰:libiconv 庫完整應用指南

     編輯:關於C語言

一、libiconv 簡介

libiconv (GNU) 提供 iconv() 族函數,支援數百種字符集互轉 (UTF-8, UTF-16, UTF-32, GBK, Big5, ISO-8859-*, CP936, Shift_JIS 等)。是跨平台編碼轉換的標準選擇。

二、核心 API

#include 

// 打開轉換描述符
iconv_t iconv_open(const char *tocode, const char *fromcode);
// tocode: 目標編碼名 (如 "UTF-8")
// fromcode: 來源編碼名 (如 "GBK")
// 回傳: 成功返回描述符,失敗返回 (iconv_t)-1

// 執行轉換
size_t iconv(iconv_t cd,
             char **inbuf, size_t *inbytesleft,
             char **outbuf, size_t *outbytesleft);
// inbuf: 輸入緩衝區位址的位址 (函數會更新指標)
// inbytesleft: 輸入剩餘位元組數 (輸入/輸出參數)
// outbuf: 輸出緩衝區位址的位址
// outbytesleft: 輸出剩餘空間 (輸入/輸出參數)
// 回傳: 成功返回轉換不可逆字符數,失敗返回 (size_t)-1 並設 errno

// 關閉描述符
int iconv_close(iconv_t cd);

三、常見錯誤碼

errno含義
EILSEQ輸入位元組序列在來源編碼中無效
EINVAL輸入不完整 (如截斷的多位元組字符)
E2BIG輸出緩衝區空間不足
EBADFcd 非有效描述符

四、完整封裝函數:安全、自動擴容、支援流式

// iconv_wrapper.h
#ifndef ICONV_WRAPPER_H
#define ICONV_WRAPPER_H
#include 

// 簡易介面:一次性轉換,自動分配輸出緩衝區 (呼叫端需 free)
char *iconv_convert(const char *fromcode, const char *tocode,
                    const char *input, size_t inlen, size_t *outlen);

// 進階介面:流式轉換器
typedef struct IconvConverter IconvConverter;
IconvConverter *iconv_open2(const char *tocode, const char *fromcode);
size_t iconv_convert2(IconvConverter *cv, const char *in, size_t inlen,
                      char **out, size_t *outlen);
void iconv_close2(IconvConverter *cv);

#endif
// iconv_wrapper.c
#include "iconv_wrapper.h"
#include 
#include 
#include 
#include 

struct IconvConverter {
    iconv_t cd;
    char *outbuf;
    size_t outcap;
};

IconvConverter *iconv_open2(const char *tocode, const char *fromcode) {
    IconvConverter *cv = malloc(sizeof(*cv));
    if (!cv) return NULL;
    cv->cd = iconv_open(tocode, fromcode);
    if (cv->cd == (iconv_t)-1) { free(cv); return NULL; }
    cv->outbuf = NULL; cv->outcap = 0;
    return cv;
}

size_t iconv_convert2(IconvConverter *cv, const char *in, size_t inlen,
                      char **out, size_t *outlen) {
    if (!cv || !in || !out || !outlen) return (size_t)-1;
    
    // 確保輸出緩衝區足夠 (最壞情況: UTF-8→UTF-32 擴大 4 倍)
    size_t need = inlen * 4 + 16;
    if (need > cv->outcap) {
        char *nb = realloc(cv->outbuf, need);
        if (!nb) return (size_t)-1;
        cv->outbuf = nb; cv->outcap = need;
    }
    
    char *inptr = (char*)in;  // 移除 const 警告
    char *outptr = cv->outbuf;
    size_t inleft = inlen, outleft = cv->outcap;
    
    size_t ret = iconv(cv->cd, &inptr, &inleft, &outptr, &outleft);
    if (ret == (size_t)-1 && errno != E2BIG) return (size_t)-1;
    
    *out = cv->outbuf;
    *outlen = cv->outcap - outleft;
    return ret;
}

void iconv_close2(IconvConverter *cv) {
    if (!cv) return;
    if (cv->cd != (iconv_t)-1) iconv_close(cv->cd);
    free(cv->outbuf);
    free(cv);
}

// 簡易一次性介面
char *iconv_convert(const char *fromcode, const char *tocode,
                    const char *input, size_t inlen, size_t *outlen) {
    IconvConverter *cv = iconv_open2(tocode, fromcode);
    if (!cv) return NULL;
    char *out = NULL; size_t olen = 0;
    size_t ret = iconv_convert2(cv, input, inlen, &out, &olen);
    iconv_close2(cv);
    if (ret == (size_t)-1) { free(out); return NULL; }
    if (outlen) *outlen = olen;
    return out;
}

五、測試驗證

#include "iconv_wrapper.h"
#include 

int main() {
    // UTF-8 → GBK
    const char *utf8 = "測試 Test 中文";
    size_t olen;
    char *gbk = iconv_convert("UTF-8", "GBK", utf8, strlen(utf8), &olen);
    if (gbk) {
        printf("GBK (%zu bytes): ", olen);
        for (size_t i=0; i

六、編譯與鏈結

gcc -o test test.c iconv_wrapper.c -liconv
# 部分系統需額外指定路徑
gcc -o test test.c iconv_wrapper.c -I/usr/local/include -L/usr/local/lib -liconv

七、進階主題

  • BOM 處理:UTF-16/32 轉換可能產生/需處理 BOM (iconv 通常自動處理,但可用 "UTF-16LE" 明確小端)。
  • 錯誤恢復:遇到 EILSEQ 可跳過非法位元組 (手動推進 inptr) 或替換為替換字符 (如 ?)。
  • 效能優化:重用 IconvConverter 避免重複 iconv_open/close;大檔案分塊處理避免巨大記憶體。
  • Windows:MSVC 可用 MultiByteToWideChar/WideCharToMultiByte 原生 API,或移植 libiconv。
  • ICU:更強大 (正規化、排序、邊界分析),但體積龐大;簡單轉換 libiconv 輕量足夠。

八、總結

libiconv 是 C 語言跨平台編碼轉換的基石。封裝 iconv_open/iconv/iconv_close 為安全、自動擴容、流式支援的介面,即可在專案中穩健處理 GBK/UTF-8/UTF-16 等互轉需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved