求iconv()函数详解

时间:2021-01-22 08:43:49
cd = iconv_open("UTF-16","UTF-8");//utf8 转UNICODE
iconv(cd,pin,&inlen,pout,&outlen)
我想知道,这个inlen 和 outlen
在调用了iconv之前和之后的值分别是代表什么意思

怎么知道我转换后的pout有多少个字节呢?

13 个解决方案

#1


NAME
       iconv - perform character set conversion

SYNOPSIS
       #include <iconv.h>

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

DESCRIPTION
       The argument cd must be a conversion descriptor created using the function iconv_open(3).

       The  main case is when inbuf is not NULL and *inbuf is not NULL.  In this case, the iconv() function converts the
       multibyte sequence starting at *inbuf to a multibyte sequence starting at *outbuf.  At most  *inbytesleft  bytes,
       starting at *inbuf, will be read.  At most *outbytesleft bytes, starting at *outbuf, will be written.

       The  iconv() function converts one multibyte character at a time, and for each character conversion it increments
       *inbuf and decrements *inbytesleft by the number of converted input bytes, it increments *outbuf  and  decrements
       *outbytesleft  by  the number of converted output bytes, and it updates the conversion state contained in cd.  If
       the character encoding of the input is stateful, the iconv() function can also convert a sequence of input  bytes
       to  an  update to the conversion state without producing any output bytes; such input is called a shift sequence.
       The conversion can stop for four reasons:

       1. An invalid multibyte sequence is encountered in the input.  In this case it sets errno to EILSEQ  and  returns (size_t) -1.  *inbuf is left pointing to the beginning of the invalid multibyte sequence.

       2.  The  input byte sequence has been entirely converted, that is, *inbytesleft has gone down to 0.  In this case
       iconv() returns the number of nonreversible conversions performed during this call.

       3. An incomplete multibyte sequence is encountered in the input, and the input byte sequence terminates after it.
       In  this  case  it sets errno to EINVAL and returns (size_t) -1.  *inbuf is left pointing to the beginning of the
       incomplete multibyte sequence.

       4. The output buffer has no more room for the next converted character.  In this case it sets errno to E2BIG  and
       returns (size_t) -1.

       A  different  case  is  when inbuf is NULL or *inbuf is NULL, but outbuf is not NULL and *outbuf is not NULL.  In
       this case, the iconv() function attempts to set cd's conversion state to the initial state  and  store  a  corre-
       sponding  shift  sequence at *outbuf.  At most *outbytesleft bytes, starting at *outbuf, will be written.  If the
       output buffer has no more room for this reset sequence, it sets errno to E2BIG and returns  (size_t) -1.   Other-
       wise it increments *outbuf and decrements *outbytesleft by the number of bytes written.

       A  third  case is when inbuf is NULL or *inbuf is NULL, and outbuf is NULL or *outbuf is NULL.  In this case, the
       iconv() function sets cd's conversion state to the initial state.

RETURN VALUE
       The iconv() function returns the number of  characters  converted  in  a  nonreversible  way  during  this  call;
       reversible conversions are not counted.  In case of error, it sets errno and returns (size_t) -1.
ERRORS
       The following errors can occur, among others:

       E2BIG  There is not sufficient room at *outbuf.

       EILSEQ An invalid multibyte sequence has been encountered in the input.

       EINVAL An incomplete multibyte sequence has been encountered in the input.

VERSIONS
       This function is available in glibc since version 2.1.

CONFORMING TO
       POSIX.1-2001.

SEE ALSO
       iconv_close(3), iconv_open(3)

#2


这个看过了,有中文的吗,看得实在晕

#3


iconv(cd,pin,&inlen,pout,&outlen)
cd-设置好的转换上下文环境
pin-输入缓冲
inlen-输入转换剩余
pout-输出缓冲
outlen-输出转换剩余

调用的过程中cd确定了从何种编码到何种编码的转换,pin为带转换的缓冲地址,inlen随着转换的进行趋近于0,转换后pout写入转换结果,同样outlen渐渐趋近于0。

#4


我测试过了
inlen:77个字节
最后返回的,
outlen:22个字节

实在搞不懂是转的什么

#5


应该还是比较好理解的,曾经发现这个函数在64bit主机上工作不正常。

#6


不同的编码方案相同的东西是用了不同的表示,所以转换前和转换后字节数不一样是很正常的,UTF-8每个字符可以是1-4字节,UTF-16没仔细研究

#7


再说那个len是表示剩余的

#8


//iconv_linux下字符集编码转换轻松实现
(1) iconv_t iconv_open(const char *tocode, const char *fromcode);
//此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
//此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
(3) int iconv_close(iconv_t cd);
//此函数用于关闭转换句柄,释放资源。

//例子1: 用C语言实现的转换示例程序

/* f.c : 代码转换示例C程序 */
#include <iconv.h>
#define OUTLEN 255
main()
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

/*unicode码转为gb2312码*/
rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
printf("unicode-->gb2312 out=%sn",out);
//gb2312码转为unicode码

rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
printf("gb2312-->unicode out=%sn",out);
}
/*代码转换:从一种编码转为另一种编码*/
int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;

cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
/*UNICODE码转为GB2312码*/
int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{
return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
/*GB2312码转为UNICODE码*/
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

//例子2: 用C++语言实现的转换示例程序

/* f.cpp : 代码转换示例C++程序 */
#include <iconv.h>
#include <iostream>

#define OUTLEN 255

using namespace std;

// 代码转换操作类

class CodeConverter {

private:
iconv_t cd;
public:

// 构造
CodeConverter(const char *from_charset,const char *to_charset) {
cd = iconv_open(to_charset,from_charset);
}


// 析构
~CodeConverter() {
iconv_close(cd);
}


// 转换输出
int convert(char *inbuf,int inlen,char *outbuf,int outlen) {
char **pin = &inbuf;
char **pout = &outbuf;

memset(outbuf,0,outlen);
return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
}
};

int main(int argc, char **argv)
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

// utf-8-->gb2312
CodeConverter cc = CodeConverter("utf-8","gb2312");
cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN);
cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;

// gb2312-->utf-8
CodeConverter cc2 = CodeConverter("gb2312","utf-8");
cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN);
cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl;
}



二、利用iconv命令进行编码转换

iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。

用法: iconv [选项...] [文件...]

有如下选项可用:

输入/输出格式规范:
-f, --from-code=名称 原始文本编码
-t, --to-code=名称 输出编码

信息:
-l, --list 列举所有已知的字符集

输出控制:
-c 从输出中忽略无效的字符
-o, --output=FILE 输出文件
-s, --silent 关闭警告
--verbose 打印进度信息

-?, --help 给出该系统求助列表
--usage 给出简要的用法信息
-V, --version 打印程序版本号

例子:
iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt
这个命令读取aaa.txt文件,从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。

小结: Linux为我们提供了强大的编码转换工具,给我们带来了方便。


#9


后边说的other case果断没理解.

#10


       A  different  case  is  when  inbuf  is NULL or *inbuf is NULL, but outbuf is not NULL and *outbuf is not NULL.  In this case, the
       iconv() function attempts to set cd's conversion state to the initial state and store a corresponding shift sequence  at  *outbuf.
       At most *outbytesleft bytes, starting at *outbuf, will be written.  If the output buffer has no more room for this reset sequence,
       it sets errno to E2BIG and returns (size_t) -1.  Otherwise it increments *outbuf and decrements *outbytesleft  by  the  number  of
       bytes written.

       A  third  case is when inbuf is NULL or *inbuf is NULL, and outbuf is NULL or *outbuf is NULL.  In this case, the iconv() function
       sets cd's conversion state to the initial state.


cs's initial state是毛玩意.

#11


set cd's conversion state to the initial state and store a corresponding shift sequence  at  *outbuf.


什么意思...

#12


inlen
outlen
都是表示剩余的空间……

#13


引用 3 楼 mscf 的回复:
iconv(cd,pin,&amp;inlen,pout,&amp;outlen)
cd-设置好的转换上下文环境
pin-输入缓冲
inlen-输入转换剩余
pout-输出缓冲
outlen-输出转换剩余

调用的过程中cd确定了从何种编码到何种编码的转换,pin为带转换的缓冲地址,inlen随着转换的进行趋近于0,转换后pout写入转换结果,同样outlen渐渐趋近于0。

这边说渐趋于0的说法不是很好,
应该是取决于未转换前的outlen的大小。

oK 结贴

#1


NAME
       iconv - perform character set conversion

SYNOPSIS
       #include <iconv.h>

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

DESCRIPTION
       The argument cd must be a conversion descriptor created using the function iconv_open(3).

       The  main case is when inbuf is not NULL and *inbuf is not NULL.  In this case, the iconv() function converts the
       multibyte sequence starting at *inbuf to a multibyte sequence starting at *outbuf.  At most  *inbytesleft  bytes,
       starting at *inbuf, will be read.  At most *outbytesleft bytes, starting at *outbuf, will be written.

       The  iconv() function converts one multibyte character at a time, and for each character conversion it increments
       *inbuf and decrements *inbytesleft by the number of converted input bytes, it increments *outbuf  and  decrements
       *outbytesleft  by  the number of converted output bytes, and it updates the conversion state contained in cd.  If
       the character encoding of the input is stateful, the iconv() function can also convert a sequence of input  bytes
       to  an  update to the conversion state without producing any output bytes; such input is called a shift sequence.
       The conversion can stop for four reasons:

       1. An invalid multibyte sequence is encountered in the input.  In this case it sets errno to EILSEQ  and  returns (size_t) -1.  *inbuf is left pointing to the beginning of the invalid multibyte sequence.

       2.  The  input byte sequence has been entirely converted, that is, *inbytesleft has gone down to 0.  In this case
       iconv() returns the number of nonreversible conversions performed during this call.

       3. An incomplete multibyte sequence is encountered in the input, and the input byte sequence terminates after it.
       In  this  case  it sets errno to EINVAL and returns (size_t) -1.  *inbuf is left pointing to the beginning of the
       incomplete multibyte sequence.

       4. The output buffer has no more room for the next converted character.  In this case it sets errno to E2BIG  and
       returns (size_t) -1.

       A  different  case  is  when inbuf is NULL or *inbuf is NULL, but outbuf is not NULL and *outbuf is not NULL.  In
       this case, the iconv() function attempts to set cd's conversion state to the initial state  and  store  a  corre-
       sponding  shift  sequence at *outbuf.  At most *outbytesleft bytes, starting at *outbuf, will be written.  If the
       output buffer has no more room for this reset sequence, it sets errno to E2BIG and returns  (size_t) -1.   Other-
       wise it increments *outbuf and decrements *outbytesleft by the number of bytes written.

       A  third  case is when inbuf is NULL or *inbuf is NULL, and outbuf is NULL or *outbuf is NULL.  In this case, the
       iconv() function sets cd's conversion state to the initial state.

RETURN VALUE
       The iconv() function returns the number of  characters  converted  in  a  nonreversible  way  during  this  call;
       reversible conversions are not counted.  In case of error, it sets errno and returns (size_t) -1.
ERRORS
       The following errors can occur, among others:

       E2BIG  There is not sufficient room at *outbuf.

       EILSEQ An invalid multibyte sequence has been encountered in the input.

       EINVAL An incomplete multibyte sequence has been encountered in the input.

VERSIONS
       This function is available in glibc since version 2.1.

CONFORMING TO
       POSIX.1-2001.

SEE ALSO
       iconv_close(3), iconv_open(3)

#2


这个看过了,有中文的吗,看得实在晕

#3


iconv(cd,pin,&inlen,pout,&outlen)
cd-设置好的转换上下文环境
pin-输入缓冲
inlen-输入转换剩余
pout-输出缓冲
outlen-输出转换剩余

调用的过程中cd确定了从何种编码到何种编码的转换,pin为带转换的缓冲地址,inlen随着转换的进行趋近于0,转换后pout写入转换结果,同样outlen渐渐趋近于0。

#4


我测试过了
inlen:77个字节
最后返回的,
outlen:22个字节

实在搞不懂是转的什么

#5


应该还是比较好理解的,曾经发现这个函数在64bit主机上工作不正常。

#6


不同的编码方案相同的东西是用了不同的表示,所以转换前和转换后字节数不一样是很正常的,UTF-8每个字符可以是1-4字节,UTF-16没仔细研究

#7


再说那个len是表示剩余的

#8


//iconv_linux下字符集编码转换轻松实现
(1) iconv_t iconv_open(const char *tocode, const char *fromcode);
//此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
//此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
(3) int iconv_close(iconv_t cd);
//此函数用于关闭转换句柄,释放资源。

//例子1: 用C语言实现的转换示例程序

/* f.c : 代码转换示例C程序 */
#include <iconv.h>
#define OUTLEN 255
main()
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

/*unicode码转为gb2312码*/
rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
printf("unicode-->gb2312 out=%sn",out);
//gb2312码转为unicode码

rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
printf("gb2312-->unicode out=%sn",out);
}
/*代码转换:从一种编码转为另一种编码*/
int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;

cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
/*UNICODE码转为GB2312码*/
int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{
return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
/*GB2312码转为UNICODE码*/
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

//例子2: 用C++语言实现的转换示例程序

/* f.cpp : 代码转换示例C++程序 */
#include <iconv.h>
#include <iostream>

#define OUTLEN 255

using namespace std;

// 代码转换操作类

class CodeConverter {

private:
iconv_t cd;
public:

// 构造
CodeConverter(const char *from_charset,const char *to_charset) {
cd = iconv_open(to_charset,from_charset);
}


// 析构
~CodeConverter() {
iconv_close(cd);
}


// 转换输出
int convert(char *inbuf,int inlen,char *outbuf,int outlen) {
char **pin = &inbuf;
char **pout = &outbuf;

memset(outbuf,0,outlen);
return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
}
};

int main(int argc, char **argv)
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

// utf-8-->gb2312
CodeConverter cc = CodeConverter("utf-8","gb2312");
cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN);
cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;

// gb2312-->utf-8
CodeConverter cc2 = CodeConverter("gb2312","utf-8");
cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN);
cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl;
}



二、利用iconv命令进行编码转换

iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。

用法: iconv [选项...] [文件...]

有如下选项可用:

输入/输出格式规范:
-f, --from-code=名称 原始文本编码
-t, --to-code=名称 输出编码

信息:
-l, --list 列举所有已知的字符集

输出控制:
-c 从输出中忽略无效的字符
-o, --output=FILE 输出文件
-s, --silent 关闭警告
--verbose 打印进度信息

-?, --help 给出该系统求助列表
--usage 给出简要的用法信息
-V, --version 打印程序版本号

例子:
iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt
这个命令读取aaa.txt文件,从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。

小结: Linux为我们提供了强大的编码转换工具,给我们带来了方便。


#9


后边说的other case果断没理解.

#10


       A  different  case  is  when  inbuf  is NULL or *inbuf is NULL, but outbuf is not NULL and *outbuf is not NULL.  In this case, the
       iconv() function attempts to set cd's conversion state to the initial state and store a corresponding shift sequence  at  *outbuf.
       At most *outbytesleft bytes, starting at *outbuf, will be written.  If the output buffer has no more room for this reset sequence,
       it sets errno to E2BIG and returns (size_t) -1.  Otherwise it increments *outbuf and decrements *outbytesleft  by  the  number  of
       bytes written.

       A  third  case is when inbuf is NULL or *inbuf is NULL, and outbuf is NULL or *outbuf is NULL.  In this case, the iconv() function
       sets cd's conversion state to the initial state.


cs's initial state是毛玩意.

#11


set cd's conversion state to the initial state and store a corresponding shift sequence  at  *outbuf.


什么意思...

#12


inlen
outlen
都是表示剩余的空间……

#13


引用 3 楼 mscf 的回复:
iconv(cd,pin,&amp;inlen,pout,&amp;outlen)
cd-设置好的转换上下文环境
pin-输入缓冲
inlen-输入转换剩余
pout-输出缓冲
outlen-输出转换剩余

调用的过程中cd确定了从何种编码到何种编码的转换,pin为带转换的缓冲地址,inlen随着转换的进行趋近于0,转换后pout写入转换结果,同样outlen渐渐趋近于0。

这边说渐趋于0的说法不是很好,
应该是取决于未转换前的outlen的大小。

oK 结贴