版权声明:本文为 西风逍遥游 原创文章,转载请注明出处 西风世界 http://blog.csdn.net/xfxyy_sxfancy

用C语言在编写一些文本处理程序时,文本编码就成为了很重要的部分,
但C语言本身,处理文本又十分困难,虽然有wchar_t这类标准库支持,
然后事实是各类编译器对其支持也不相同,而且缺乏一致的标准。

可移植的转码库libiconv

libiconv是GNU出品的一款非常方便的转码库,可以支持各类
常见编码类型。

语言 编码
欧洲语系 ASCII,
ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16},
KOI8-R, KOI8-U, KOI8-RU,
CP{1250,1251,1252,1253,1254,1257},
CP{850,866},
Mac{Roman,CentralEurope,Iceland,Croatian, Romania},
Mac{Cyrillic,Ukraine,Greek,Turkish},
Macintosh
犹太语系 ISO-8859-{6,8}, CP{1255,1256}, CP862, Mac{Hebrew,Arabic}
日文 EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP,
ISO-2022-JP-2, ISO-2022-JP-1
中文 EUC-CN, HZ, GBK, GB18030, EUC-TW, BIG5, CP950,
BIG5-HKSCS, ISO-2022-CN, ISO-2022-CN-EXT
朝鲜文 EUC-KR, CP949, ISO-2022-KR, JOHAB
亚美尼亚语 ARMSCII-8
格鲁尼亚语 Georgian-Academy, Georgian-PS
塔吉克语 KOI8-T
泰国语 TIS-620, CP874, MacThai
老挝语 MuleLao-1, CP1133
越南语 VISCII, TCVN, CP1258
特殊平台 HP-ROMAN8, NEXTSTEP
全部Unicode UTF-8, UTF-7
UCS-2, UCS-2BE, UCS-2LE, UCS-4, UCS-4BE, UCS-4LE
UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, UTF-32LE
C99, JAVA

计算机内部处理,比较喜欢用Unicode这类覆盖字符集全的,而且一般选择固定长度字符的,像UTF-8这类变长字符集,会给字符处理算法带来困难。

于是一般的字符转码思路就是,将用户的输入字符集识别出来,转换成内部表示形式,一般个人喜欢选UTF-32,比较方便,而且覆盖字符集很全。
输出时,再将内部格式转换为用户需要的编码格式进行输出即可。像linux控制台,就可以直接输出UTF-8编码的字符串。Windows中文同样可以输出CP936编码的文本。

发现用户文件的编码

很多情况下,要读取的文件的编码可能不是很好确定,尤其是文件中并没有保存任何编码格式的相关信息时,这时我们只能靠尝试,用多种解码器进行解码,出错最少的,我们才认为成功。
自行编写该解码尝试器,难度和编码转换器类似,都要对编码格式深入了解才行,那么一般我们要使用该功能时,只需引入一个非常强大得到探测器库就可以了。

Mozilla Universal Character Set Detector,是一款强大的编码探测器库,具有操作简单,识别格式广的特点。其仓库地址:
https://github.com/batterseapower/libcharsetdetect

支持的探测格式更是有:

Big5
EUC-JP
EUC-KR
GB18030
gb18030
HZ-GB-2312
IBM855
IBM866
ISO-2022-CN
ISO-2022-JP
ISO-2022-KR
ISO-8859-2
ISO-8859-5
ISO-8859-7
ISO-8859-8
KOI8-R
Shift_JIS
TIS-620
UTF-8
UTF-16BE
UTF-16LE
UTF-32BE
UTF-32LE
windows-1250
windows-1251
windows-1252
windows-1253
windows-1255
x-euc-tw
X-ISO-10646-UCS-4-2143
X-ISO-10646-UCS-4-3412
x-mac-cyrillic

安装

这两款库的安装都非常简单,下载下来依次进行

./configure
make

这样就可以了

libiconv稍微麻烦,如果出现这个错误:
error: ‘gets’ undeclared here (not in a function)

是因为srclib/stdio.in.h这个文件695行有个bug,没检测GLIBC的版本所致:

--- srclib/stdio.in.h.orig 2011-08-07 16:42:06.000000000 +0300
+++ srclib/stdio.in.h 2013-01-10 15:53:03.000000000 +0200
@@ -695,7 +695,9 @@/* It is very rare that the developer ever has full control of stdin,so any use of gets warrants an unconditional warning.  Assume it isalways declared, since it is required by C89.  */
-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
+#if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
+ _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
+#endif#endif

使用

libcharsetdetect的官网带有一个示例,很成功的运行起来,也没发现什么问题:

#include "charsetdetect.h"
#include "stdio.h"#define BUFFER_SIZE 4096int main(int argc, const char * argv[]) {csd_t csd = csd_open();  // 首先开启一个探测器if (csd == (csd_t)-1) {printf("csd_open failed\n");return 1;}int size;char buf[BUFFER_SIZE] = {0}; // 这里建议用memset避免部分编译器报错while ((size = fread(buf, 1, sizeof(buf), stdin)) != 0) {int result = csd_consider(csd, buf, size);if (result < 0) {printf("csd_consider failed\n");return 3;} else if (result > 0) {// Already have enough databreak;}}const char *result = csd_close(csd);if (result == NULL) {printf("Unknown character set\n");return 2;} else {printf("%s\n", result);return 0;}
}

编译运行即可:

gcc example.c -lcharsetdetect
./a.out < my_test_file.txt

libiconv比较反人类,build后,库和so文件都藏在各个目录里,没有install的化,就得自己找出来。
还好如果我们只是引用其中的转码功能,只需要lib/.libs/libiconv.so这个文件,注意,是这个软链接指向的目标。
头文件就拿include下的就好。

使用上来看,这个库的用法非常诡异,也是分三步:

iconv_t cd = iconv_open("to_code", "from_code"); // 确定要转换的编码
size_t nconv = iconv (cd, &inptr, &in_size, &outptr, &out_size); // 输入输出数据
iconv_close (cd); // 回收资源

iconv是其核心转换函数,其定义如下:

size_t iconv (iconv_t cd,const char* * inbuf, size_t * inbytesleft,char* * outbuf, size_t * outbytesleft);

首先解释一下各个参数的含义
cd是转换描述用的结构体,inbuf是指向输入数据的指针的指针,outbuf类似,
inbytesleft,outbytesleft也是两个指针。

这个函数工作时,所有的指针都在变化,*inbuf 会不断自增扫描, *outbuf会不断向后移动填写数据, 而 *inbytesleft 则表示输入数组还剩多少字节,注意单位都是字节。 *outbytesleft 同理,表示输出数组还剩的剩余空间。
当 *inbytesleft 为 0 时,表示输入完毕,而 *outbytesleft 为 0 后,会触发剩余空间不足的错误,方便你重新分配空间。

完整示例和封装

我将两个库结合在了一起,封装成了一个自动文本读取并转换的库,方便使用,代码仓库:
https://github.com/sunxfancy/ExIconv

C语言自动识别文本编码相关推荐

  1. c语言自动转化,C语言编程之自动类型转化

    咱们在写程序的时候经常会遇到一些不好找的bug,有的并不是很难,只是大家容易忽略,今天咱们就来看一个,关于C语言自动类型转换的bug. 先看一段代码: void getNext(int * next, ...

  2. Swift3.0语言教程使用编码创建和初始化字符串

    Swift3.0语言教程使用编码创建和初始化字符串 使用编码创建和初始化字符串 创建和初始化字符串除了可以使用上文中提到的方法外,还可以使用init(coder:)方法,此方法一般不常使用,其语法形式 ...

  3. gocode+auto-complete搭建emacs的go语言自动补全功能

    上篇随笔记录了在emacs中使用go-mode和goflymake搭建了go语言的简单编程环境(推送门),今天来记录一下使用gocode+auto-complete配置emacs中go语言的自动补全功 ...

  4. java ee自动生成编码_EE Servlet 3:在Servlet中生成HTML输出

    java ee自动生成编码 如果您只需要在EE Web模块中处理少量请求URI,那么在Servlet代码中生成自己HTML响应可能比使用完整的模板库更容易. 作为示例的一部分,我尝试了一个非常简单的J ...

  5. r语言处理数据集编码_在强调编码语言或工具之前,请学习这3个基本数据概念

    r语言处理数据集编码 重点 (Top highlight) I got an Instagram DM the other day that really got me thinking. This ...

  6. AX2012 学习自动生成编码

    模仿NumberSeq写一个自动生成编码的功能. 起初只是简单通过读取数据库中最后的一个值来生成作为当前最大值,然后通过逻辑处理加1就生成了新的值.但是这之中就隐含了一个问题,线程的同步问题.由于多个 ...

  7. RHEL7及CentOS7的语言、字符编码、键盘映射、X11布局设置(localectl)-系统管理(1)...

    这几天在阅读Red Hat Enterprise Linux 7的官方文档,发现了一些比之前有较大改善的系统管理方式,准备用一个系列的文章来分享一下自己的阅读.学习心得.在系统管理指导的开篇就提到了语 ...

  8. C语言自动预订飞机票问题

    C语言自动预订飞机票问题 2.自动预订飞机票问题(难度2) 设民航公司有一个自动预订飞机票的系统.该系统中有一张用单向链表表示的乘客表,下表中的结点按乘客姓氏的字母顺序相链.例如,下面是张某个时刻的乘 ...

  9. 基于C语言的JPEG编码代码详解

    一.基于C语言的JPEG编码代码详解 #include <stdio.h> #include <stdlib.h> #include <string.h>#prag ...

最新文章

  1. Sprites实现翻页按钮,圆角,宽度不固定
  2. 算法------------数组----------------两个数组的交集 II
  3. slf4j 和 log4基础入门(Maven配置)
  4. 01pxc集群的部署
  5. h5 rtmp推荐控件_H5播放Rtmp之videojs播放
  6. zabbix server is not running the information displayed may not be current
  7. rust程序设计语言第二版_C语言程序设计(山东联盟青岛大学版)
  8. 用wrk测试nginx/nodejs/golang
  9. ERROR:ModuleNotFoundError: No module named ‘cv2‘
  10. c#文件分割与合并 part 1 (转自互联网)
  11. 集成电路哪家强?现在就为你透彻分析!
  12. 一张图片即可入侵你的电脑
  13. Python中scipy库的pearsonr(x, y)的使用
  14. 音视频开发技术,让智能家居更智能!
  15. python统计股票上涨天数
  16. 文件服务器批量权限修改,服务器文件批量权限设置权限
  17. 知其然,而不知其所以然
  18. R实战 | 山脊图(ridgeline plot)
  19. STI、LOD与WPE概念:形成机理及对电路设计的影响
  20. 华硕计算机硬件信息,ASUS PC Diagnostics

热门文章

  1. 设备检修管理系统有哪些功能特点?
  2. 安卓sip话机/一款基于linphone开发的,安卓sip话机客户端
  3. 深度分享:中国老年消费市场最新趋势/机会是什么?六位老年行业创新创业实践者精彩观点!
  4. 计算机科学与技术系导师名单,西南交通大学计算机科学与技术系研究生导师介绍:蒋朝根...
  5. 规范化git commit信息
  6. 国开计算机组成原理边学边练,国家开放大学-计算机组成原理-形考任务-2017全部答案.docx...
  7. 带你了解「美团、百度和滴滴」的分布式 ID 生成系统
  8. STM32MP157驱动开发——4G通信模块驱动
  9. Elasticsearch分布式搜索笔记
  10. Vue3表单验证 单个验证 统一验证 自定验证