为博罗等地区用户提供了全套网页设计制作服务,及博罗网站建设行业解决方案。主营业务为网站制作、成都网站建设、博罗网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
场景说明
将UTF-8的编码转换成GBK编码,使用Notepad++创建一个UTF-8(无BOM)的编码文件,文件内容简单为风雨在途,保存文件名称为utf8.txt,转换之后存储文件名称为gbk.txt.
iconv -f UTF8 -t GBK
#include
size_t iconv(iconv_t cd,
char **inbuf, size_t*inbytesleft,
char **outbuf, size_t*outbytesleft);
参数说明:经过iconv函数之后,*outbuf当前指向转换之后的字符串的最后位置,*inuf当前指向被转换字符串的最后位置,所以为了得到正确的转换字符串的指针位置,需要进行如下的调整:
*outbuf = *outbuf - iconv函数的返回值.或者定义指针指向当前的字符串缓存区,就不会修改字符串的缓冲区指针了
int UTF8fileToGBKfile()
{
int ret;
int read_fd;
int write_fd;
//1打开文件,读取utf-8文件
read_fd=open("utf8.txt",O_RDONLY|O_CREAT);
write_fd=open("gbk.txt", O_WRONLY|O_CREAT);
char utfBuffer[256] = {0};
size_t inLen = read(read_fd, utfBuffer,256);
//2获取字符集转换的文件句柄,这里是从utf-8转换为gbk
errno = 0;
iconv_t cd = iconv_open("gbk","utf-8");
char* errMsg = NULL;
if (errno !=0)
{
errMsg = strerror(errno);
cout< cout< return -1; } //3准备转换前的字符串,避免修改原字符串 char* szSrc = (char*)malloc(inLen); memset(szSrc, 0, inLen); memcpy(szSrc, utfBuffer, inLen); //4准备转换后的字符串存储空间 size_t outLen = 256; char* szDest = (char*)malloc(outLen); memset(szDest, 0, outLen); //4开始转换 errno = 0; char* pszDest = szDest; char* pszSrc = szDest; errno = 0; ret = iconv(cd, &pszSrc, &inLen,&pszDest , &outLen); if (errno !=0) { errMsg = strerror(errno); cout< cout< return -2; } iconv_close(cd); //5写入文件,outlen是剩下多少空间没有使用 ret = write(write_fd, szDest, 256-outLen); close(read_fd); close(write_fd); free(szDest); free(szSrc); return 0; } 下载libiconv-1.14.tar.gz,解压,执行./configure --prefix=/opt/iconv;make;make install 生成文件: charset.alias libcharset.so libiconv.la libiconv.so.2.5.1 libcharset.a libcharset.so.1 libiconv.so preloadable_libiconv.so libcharset.la libcharset.so.1.0.0 libiconv.so.2 实际链接到库的时候,指定库目录,在/etc/ld.so.conf文件之后追加一行/opt/iconv/lib.采用ldconfig命令的时候,出错: libcharset.so.1 不是符号链接 libiconv.so.2 不是符号链接 原因是:删除这两个文件,然后使用ldconfig命令,生成该符号链接。 [root@jack lib]# ll 总用量 3560 -rw-r--r--. 1 root root 212 9月 13 10:22 charset.alias -rw-r--r--. 1 root root 27868 9月 13 10:22 libcharset.a -rw-r--r--. 1 root root 936 9月 13 10:22 libcharset.la -rw-r--r--. 1 root root 277609月 13 10:22 libcharset.so lrwxrwxrwx. 1 root root 19 9月 13 11:10libcharset.so.1->libcharset.so.1.0.0 -rw-r--r--. 1 root root 27760 9月 13 10:22 libcharset.so.1.0.0 -rw-r--r--. 1 root root 912 9月 13 10:22 libiconv.la -rw-r--r--. 1 root root 1186436 9月 13 10:22 libiconv.so lrwxrwxrwx. 1 root root 17 9月 13 11:10 libiconv.so.2 ->libiconv.so.2.5.1 -rw-r--r--. 1 root root 1186436 9月 13 10:22 libiconv.so.2.5.1 -rw-r--r--. 1 root root 1168119 9月 13 10:22 preloadable_libiconv.so 调用该动态库的编译命令如下: g++ test.cpp -I/opt/iconv/include//opt/iconv/lib/libcharset.a/opt/iconv/lib/libiconv.so libsqlite3.a-lpthread -ldl -g -o main ./configure--prefix=/opt/iconvCFLAGS="-g -O0" 生成动态库链接符号错误解决 [root@jack lib]# ldconfig ldconfig: /opt/iconv/lib/libiconv.so.2 不是符号连接 ldconfig: /opt/iconv/lib/libcharset.so.1 不是符号连接 [root@jack lib]# rm -rflibiconv.so.2libcharset.so.1 [root@jack lib]# ldconfig 主要是将UTF-8编码的字符串在转换成GBK编码,详细的转换规则UTF-8转Unicode, 然后Unicode编码通过查表,映射到GBK编码上 loop_unicode.h:273 执行函数 incount=cd->ifuncs.xxx_mbtowc(cd,&wc,inptr,inleft); 跳转到./utf8.h:30 核心转换函数:static size_t unicode_loop_convert (iconv_t icd, const char* * inbuf, size_t *inbytesleft,char* *outbuf,size_t*outbytesleft) at./loop_unicode.h:284 284 incount = cd->ifuncs.xxx_mbtowc(cd,&wc,inptr,inleft); at./loop_unicode.h:362 362 outcount = cd->ofuncs.xxx_wctomb(cd,outptr,wc,outleft); 该函数进行Unicode转换成GBK 进行的是查表进行转换,在调试的过程中,可以通过附件,提前知道转换的字符编码,然后查看iconv库是否转换有问题 UTF-8转Unicode编码的函数: static int utf8_mbtowc (conv_t conv, ucs4_t*pwc,constunsigned char *s, int n) iconv函数中传递进去的outptr会指向转换字符串的末尾,所以需要进行指针的前移,outptr-返回值 就是指向最开始转换的字符串 iconv_open函数跳转到lib/iconv.c 218 行,里面调用了 #include "iconv_open1.h" 47-60行 141-152行 for (cp = fromcode, bp = buf, count = MAX_WORD_LENGTH+10+1; ; cp++,bp++){ unsigned char c = * (unsigned char *) cp; if (c >= 0x80) goto invalid; if (c >= 'a' && c <= 'z') c -= 'a'-'A'; *bp = c; if (c == '\0') break; if (--count == 0) goto invalid; } 这里进行了大小写转换,所有的字体编码类型,转换成大写字母,gbk转换成GBK.小写字母转换成大写字母是减去26 目前遇到一个相当大的问题: ap= aliases_lookup(buf,bp-buf); if(ap == NULL) { ap = aliases2_lookup(buf); if (ap == NULL) goto invalid; } 这几行函数没能够单步调试所以并不清楚返回值进行了什么操作 #include "iconv_open2.h" 设置执行的回调函数,以及初始化标志位,具体的没有看出什么 使用库提供的automake,顺利生成libiconv.so文件,目前尝试单独编译,出现如下的问题 使用指令如下: g++libiconv-1.14/libcharset/lib/localcharset.clibiconv-1.14/lib/iconv.clibiconv-1.14/lib/relocatable.c libsqlite3.a -lpthread -ldl -Ilibiconv-1.14/-I libiconv-1.14/include/-I libiconv-1.14/lib-Ilibiconv-1.14/libcharset/include/ -fPIC -shared -o libiconv.so libiconv-1.14/libcharset/lib/localcharset.c:77:25:错误:configmake.h:没有那个文件或目录 libiconv-1.14/libcharset/lib/localcharset.c:Infunction‘const char* get_charset_aliases()’: libiconv-1.14/libcharset/lib/localcharset.c:135:错误:‘LIBDIR’在此作用域中尚未声明 查找资料显示在windows下无需该文件,因此注释该头文件的包含 问题剩下LIBDIR的定义问题 查找所有的引用LIBDIR ,localcharset.c函数 static const char*get_charset_aliases(void)会通过dir =relocate (LIBDIR); 获取该值,查看该函数的内容: const char *cp; cp=charset_aliases; /* Pointer to the contentsofthecharset.alias file, if it has already been read, else NULL. Its format is: ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0'CANONICAL_n '\0''\0' */ static const char *volatilecharset_aliases; 说明指向这个charset.alias文件,查看该文件: 该文件的目录如下: libiconv-1.14/libcharset/lib 内容如下: # This file contains a table ofcharacterencodingaliases, # suitable for operating system'linux-gnu'. # It was automatically generatedfromconfig.charset. # Packages using this file: ISO_646.IRV:1983 ASCII 说明该文件是由同一级目录下的config.charset脚本生成的 跟踪: linux* | *-gnu*) #With glibc-2.1 or newer, we don't need any canonicalization, #because glibc has iconv and both glibc and libiconv support all #GNU canonical names directly. Therefore, the Makefile does not #need to install the alias file at all. #The following applies only to glibc-2.0.x and older libcs. echo "ISO_646.IRV:1983 ASCII" 翻译:glibc-2.1以后的版本都不需要任何的标准化文件,因为自带的缘故,该文件只是被之前的版本引用 因此在localcharset.c 定义LIBDIR指向的目录: #defineLIBDIR"/work/libiconv-1.14/libcharset/lib" [root@jack work]# g++libiconv-1.14/libcharset/lib/localcharset.clibiconv-1.14/lib/relocatable.c libiconv-1.14/lib/iconv.c test.cpp -I libiconv-1.14/ -Ilibiconv-1.14/lib/-Ilibiconv-1.14/include -Ilibiconv-1.14/libcharset/include/ -I libiconv-1.14/srclib/ libsqlite3.a -lpthread -ldl -o testmain /tmp/cc1ENLex.o: Infunction`libiconv_open': iconv.c:(.text+0x18206):undefinedreferenceto `aliases_lookup(char const*, unsigned int)' iconv.c:(.text+0x18391):undefinedreferenceto `aliases_lookup(char const*, unsigned int)' /tmp/cc1ENLex.o:Infunction`libiconv_open_into': iconv.c:(.text+0x187d0): undefinedreferenceto`aliases_lookup(char const*, unsigned int)' iconv.c:(.text+0x1895b):undefinedreferenceto `aliases_lookup(char const*, unsigned int)' /tmp/cc1ENLex.o: Infunction`iconv_canonicalize': iconv.c:(.text+0x190a9):undefinedreferenceto `aliases_lookup(char const*, unsigned int)' collect2: ld 返回 1 该函数的定义就在lib/aliases.h文件当中定义的,不清楚为什么无法找到, 然后手动将该定义拷贝到lib/iconv.c文件,还是出现同样子的问题2 编译调试
2.1禁用优化安装
2.2禁用优化
2.3 GDB调试源码
2.4手动编写指令构建动态库
当前文章:iconv用法
分享链接:http://cdweb.net/article/peissp.html