千家信息网

iconv 用法

发表于:2025-02-13 作者:千家信息网编辑
千家信息网最后更新 2025年02月13日,iconv 用法场景说明将UTF-8的编码转换成GBK编码,使用Notepad++创建一个UTF-8(无BOM)的编码文件,文件内容简单为风雨在途,保存文件名称为utf8.txt,转换之后存储文件名称
千家信息网最后更新 2025年02月13日iconv 用法

iconv 用法

场景说明

UTF-8的编码转换成GBK编码,使用Notepad++创建一个UTF-8(无BOM)的编码文件,文件内容简单为风雨在途,保存文件名称为utf8.txt,转换之后存储文件名称为gbk.txt.

1.1iconv命令的使用

iconv -f UTF8 -t GBK gbk.txt

1.2iconv函数的使用

#include

size_t iconv(iconv_t cd,

char **inbuf, size_t*inbytesleft,

char **outbuf, size_t*outbytesleft);

参数说明:经过iconv函数之后,*outbuf当前指向转换之后的字符串的最后位置,*inuf当前指向被转换字符串的最后位置,所以为了得到正确的转换字符串的指针位置,需要进行如下的调整:

*outbuf = *outbuf - iconv函数的返回值.或者定义指针指向当前的字符串缓存区,就不会修改字符串的缓冲区指针了

1.3代码如下

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;

}

2 编译调试

2.1禁用优化安装

下载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

2.2禁用优化

./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

2.3 GDB调试源码

主要是将UTF-8编码的字符串在转换成GBK编码,详细的转换规则UTF-8Unicode

然后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-8Unicode编码的函数:

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"

设置执行的回调函数,以及初始化标志位,具体的没有看出什么

2.4手动编写指令构建动态库

使用库提供的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文件,还是出现同样子的问题


文件 函数 字符 字符串 编码 指向 符号 问题 目录 链接 UTF-8 生成 命令 指针 位置 内容 动态 字母 错误 utf-8 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 万象城广场网络安全宣传 大白u帮软件开发用了多少钱 服务器ftp设置 北京易诚互动网络技术 传奇服务器被攻击上不去 无法连接至授权服务器稍后再试 用自己的数据库 福建http服务器云主机 奥维互动地图基于什么软件开发 实验10数据库安全性 是德科技工业互联网 数据库float精度损失 网络安全冬奥会总结个人 网络安全与管理课程设计 武汉大学网络安全专业好就业吗 认证服务器的作用 搬瓦工服务器安全吗 陕西志成新业网络技术 计算机网络技术是那个部的 网络安全设备能用多少年 软件开发后期维护免税怎么开票 软件开发一般用什么上传代码 服务器管理终端命令 登录服务器的管理界面 中文数据库名称及检索式 油料网络技术 计算机网络技术要找工作吗 浦东新区海航数据库服务电话多少 网络安全员工作环境图片 绝地求生刺激战场显示服务器问题
0