from:http://blog.csdn.net/qianguozheng/article/details/46429245

// 代码转换操作类
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_utf,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命令进行编码转换
在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用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为我们提供了强大的编码转换工具,给我们带来了方便。 glibc带了一套转码函数iconv,使用方便,可识别的码很多,如果程序需要涉及到编码之间的转换,可考虑用它。 iconv命令的用法。 $ iconv --list # 显示可识别的编码名称
$ iconv -f GB2312 -t UTF-8 a.html > b.html # 转换GB2312编码的文件a.html为UTF-8编码,存入b.html
$ iconv -f GB2312 -t BIG5 a.html > b.html # 转换GB2312编码的文件a.html为BIG5编码,存入b.html
iconv编程涉及到以下glibc库的调用: #include <iconv.h> iconv_t iconv_open(const char *tocode, const char *fromcode);
int iconv_close(iconv_t cd); size_t iconv(iconv_t cd,
char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft); 在使用iconv转码的时候,首先用iconv_open获取转码句柄,然后调用iconv转码,转完了后调用iconv_close关闭句柄。 iconv函数中: 参数cd是用iconv_open调用返回的转码句柄;
参数inbuf指向需要转码的缓冲区;
参数inbytesleft是inbuf所保存的需要转码的字节数;
参数outbuf存放转码结果;
参数outbytesleft存放outbuf空间的大小。 如果调用成功,iconv返回转换的字节数(不可逆转调用的字节数,可逆转调用的字节数不包括在内)。否则返回-1,并设置相应的errno。
iconv逐步扫描inbuf,每转换一个字符,就增加inbuf,减少inbytesleft,并将结果存入outbuf,结果字节数存入 outbytesleft。遇到下列情况将停止扫描并返回: 1. 多字节序列无效,这时候errno为EILSEQ,*inbuf指向第一个无效的字符;
2. 有字节留在inbuf尚未转换,errno为EINVAL;
3. outbuf空间不够,errno为E2BIG;
4. 正常转换完备。 对于iconv函数,还有两种调用情况: 1. inbuf或者*inbuf为NULL,outbuf和*outbuf不为NULL,iconv会设置转换状态为初始状态,并保存转换序列到*outbuf。如果outbuf空间不足,errno会设置为E2BIG,返回(size_t)(-1);
2. inbuf或者*inbuf为NULL,outbuf或者*outbuf也为NULL,iconv设置转换状态为初始状态。 iconv命令的使用固然方便,可是如果转换过程中如果遇到问题则会停止转换,有时候我们希望跳过不能转换的字节序列继续转换。以下的一段程序能实现这种功能。 /**
* siconv.cpp - A simple way to demostrate the usage of iconv calling
*
* Report bugs to marchday2004@yahoo.com.cn
* July 15th, 2006
*/
#include <iconv.h>
#include <stdio.h>
#include <string>
#include <stdarg.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h> #ifdef DEBUG
#define TRACE(fmt, args...) fprintf(stderr, "%s:%s:%d:"fmt, \
__FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define TRACE(fmt, args...)
#endif #define CONVBUF_SIZE 32767 extern int errno; void print_err(const char *fmt, ...)
{
va_list ap; va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
} int print_out(const char* buf, size_t num)
{
if (num != fwrite(buf, 1, num, stdout)) {
return -1;
} return 0;
} void print_usage() { print_err("Usage: siconv -f encoding -t encoding [-c] "
"input-file\n";
} int iconv_string(const char *from, const char *to,
const char *src, size_t len,
::std::string& result,
int c = 0, size_t buf_size = 512)
{
iconv_t cd; char *pinbuf = const_cast< char* >(src);
size_t inbytesleft = len;
char *poutbuf = NULL;
size_t outbytesleft = buf_size; char *dst = NULL;
size_t retbytes = 0;
int done = 0;
int errno_save = 0; if ((iconv_t)-1 == (cd = iconv_open(to, from))) {
return -1;
} dst = new char[buf_size]; while(inbytesleft > 0 && !done) {
poutbuf = dst;
outbytesleft = buf_size; TRACE("TARGET - in:%p pin:%p left:%d\n", src, pinbuf, inbytesleft);
retbytes = iconv(cd, &pinbuf, &inbytesleft, &poutbuf, &outbytesleft);
errno_save = errno; if (dst != poutbuf) {// we have something to write
TRACE("OK - in:%p pin:%p left:%d done:%d buf:%d\n",
src, pinbuf, inbytesleft, pinbuf-src, poutbuf-dst);
result.append(dst, poutbuf-dst);
} if (retbytes != (size_t)-1) {
poutbuf = dst;
outbytesleft = buf_size;
(void)iconv(cd, NULL, NULL, &poutbuf, &outbytesleft); if (dst != poutbuf) {// we have something to write
TRACE("OK - in:%p pin:%p left:%d done:%d buf:%d\n",
src, pinbuf, inbytesleft, pinbuf-src, poutbuf-dst);
result.append(dst, poutbuf-dst);
} errno_save = 0;
break;
} TRACE("FAIL - in:%p pin:%p left:%d done:%d buf:%d\n",
src, pinbuf, inbytesleft, pinbuf-src, poutbuf-dst); switch(errno_save) {
case E2BIG:
TRACE("E E2BIG\n";
break;
case EILSEQ:
TRACE("E EILSEQ\n";
if (c) {
errno_save = 0;
inbytesleft = len-(pinbuf-src); // forward one illegal byte
inbytesleft--;
pinbuf++;
break;
} done = 1;
break;
case EINVAL:
TRACE("E EINVAL\n";
done = 1;
break;
default:
TRACE("E Unknown:[%d]%s\n", errno, strerror(errno));
done = 1;
break;
} } delete[] dst;
iconv_close(cd); errno = errno_save;
return (errno_save) ? -1 : 0;
} int conv_file_fd(const char* from, const char *to, int fd,
::std::string& result, int c)
{
struct stat st;
void *start; if (0 != fstat(fd, &st)) {
return -1;
} start = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (MAP_FAILED == start) {
return -1;
} if (iconv_string(from, to, (char*)start,
st.st_size, result, c, CONVBUF_SIZE) < 0) {
int errno_save = errno;
munmap(start, st.st_size);
TRACE("\n";
errno = errno_save;
return -1;
} munmap(start, st.st_size);
return 0;
} int conv_file(const char* from, const char* to,
const char* filename, int c)
{
::std::string result;
FILE *fp; if (NULL == (fp=fopen(filename, "rb")) {
print_err("open file %s:[%d]%s\n", filename,
errno, strerror(errno));
return -1;
} if (conv_file_fd(from, to, fileno(fp), result, c) < 0) {
print_err("conv file fd:[%d]%s\n", errno, strerror(errno));
fclose(fp);
return -1;
} print_out(result.data(), result.size());
fclose(fp);
return 0;
} int main(int argc, char *argv[])
{
#ifdef TESTCASE
::std::string strA = "欢迎(welcome ^_^)来到(to)首都北京。";
::std::string strB = "大喊一声:We are chinese <=> 我们都是中国人。"; ::std::string strC = strA.substr(0, 20) + strB.substr(0, 41);
::std::string result;
if (iconv_string("GBK", "UTF-8", strC.data(), strC.size(), result, 1) < 0)
{
TRACE("ERROR [%d]%s\n", errno, strerror(errno));
} TRACE("CONVERSION RESULT:";
result.append("\n";
print_out(result.data(), result.size()); return 0;
#else
::std::string from, to;
::std::string input_file;
int o;
int c = 0; while (-1 != (c = getopt(argc, argv, "f:t:c")))
{
switch(c) {
case 'f':
from = optarg;
break;
case 't':
to = optarg;
break;
case 'c':
c = 1;
break;
default:
return -1;
}
} if (from.empty() || to.empty() || optind != (argc-1))
{
print_usage();
return -1;
} input_file = argv[optind++]; return conv_file(from.c_str(), to.c_str(),
input_file.c_str(), c);
#endif
} 可以用内存映像文件解决文件太大内存缓冲不够的情况。相对于iconv命令,加-c选项,以忽略转换过程中可能引发的问题。 $ g++ -o siconv siconv.cpp
如果在命令行加了-DDEBUG选项,会编译进调试语句,如果加了-DTESTCASE选项,则仅会编译对iconv_string函数测试的情况。

utf8转为gb2312的函数的更多相关文章

  1. php使用iconv进行从utf-8转为gb2312字符编码出错或截断的解决方案

    iconv("GB2312","UTF-8",$text);修改为以下其中一种:1.iconv("UTF-8","GBK" ...

  2. JAVA js的escape函数、解析用js encodeURI编码的字符串、utf8转gb2312的函数

    在使用webView时,如果url中参数有中文的话,拦截到的字符串就会类似这样的:http://api.letstar.cn/zq/news.html?id=20&cupName=%E6%B5 ...

  3. UTF-8和GB2312互转的最简单快捷的方法

    一.如果你想把utf-8转为GB2312 1.用记事本打开源码,把<meta http-equiv="Content-Type" content="text/htm ...

  4. UTF-8、GB2312都支持的汉字截取函数

    <?php/*Utf-8.gb2312都支持的汉字截取函数cut_str(字符串, 截取长度, 开始长度, 编码);编码默认为 utf-8开始长度默认为 0*/ function cut_str ...

  5. 【转】python XML 操作总结(创建、保存和删除,支持utf-8和gb2312)

    原文地址:http://hi.baidu.com/tbjmnvbagkfgike/item/6743ab10af43bb24f6625cc5 最近写程序需要用到xml操作,看了看python.org上 ...

  6. 编辑器source insight,sublime,编码 utf-8和 GB2312

    source insight中,想要UTF-8的中文字符正常显示的话,目前没有直接支持的方法. 暂时只能通过将原UTF-8的格式的文件,转换为本地ANSI编码(此处是简体中文,对应的ANSI编码为GB ...

  7. C语言编码转换gb2312 to utf8,utf8 to gb2312 代码,GCC编译,支持Windows、Linux

    编译:gcc -o f.exe f.c -liconv #include <stdio.h> #include <stdlib.h> #include <stddef.h ...

  8. UTF-8, Unicode, GB2312格式串转换之C语言版

    原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html           /*      author:   wu.j ...

  9. 在js里UTF-8与GB2312的互转

    js的函数如下: function GB2312UTF8() { this.Dig2Dec = function(s) { var retV = 0; if (s.length == 4) { for ...

随机推荐

  1. Webdriver:Unsupported Marionette protocol version 2, required 3

    升级到firefox到47以上版本即可 坑人的Mozilla不能起个我们熟识的名字吗? 先是webdriver.gecko.driver后是Marionette protocol.   1.WebDr ...

  2. 用C#来查看电脑硬件和系统信息

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用C#来查看电脑硬件和系统信息.

  3. 记RedisDesktopManager的一次崩溃

    redis3.2的配置文件中有bind监听地址 bind 192.168.42.131默认bind的填写的127.0.0.1这样配置是只允许本地访问,如果想远程访问就改为本机网卡绑定的ip地址.我这边 ...

  4. 【开发工具 - Git】之Git常用命令汇总

    本文记录了Git Bash中的常用指令. 1       Git操作 git clone XXXXX:将GitHub项目XXXXX克隆到本地 git remote –v:查看远程连接信息 git ch ...

  5. String的点点滴滴

    一.String 的 equals()到底比较的是什么?equals() 与 == 的区别? 当使用关系运算符==比较两个对象时,是比较两个对象使用的内存地址和内容是否相同,如果两个对象使用的是同一个 ...

  6. Android虚拟机Dalvik介绍

     Dalvik和标准Java虚拟机(JVM)之间的首要差别之一,就是Dalvik基于寄存器,而JVM基于栈.一直以来都有人在猜测,选择基于寄存器的方式是因为它对提前优化(ahead-of-time o ...

  7. 征服 Nginx + Tomcat【转】

    征服 Nginx + Tomcat Server Architecture/Distributed nginxtomcatsessioncluster  2年前一直折腾Apache,现如今更习惯Ngi ...

  8. [Whole Web, Nods.js, PM2] Passing environment variables to node.js using pm2

    learn how to pass environment variables to your node.js app using the pm2 config file. This is usefu ...

  9. mysql选择联合索引还是单索引?索引列应该使用哪一个最有效?深入測试探讨

    先建表 CREATE TABLE `menu_employee` ( `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键,无实际意义', `emplo ...

  10. 【转】C/C++求模求余运算符——2013-08-20

    http://blog.csdn.net/whealker/article/details/6203629 求模运算符(%),或称求余运算符,也就是数学上所谓的除法中的余数,%两侧均应为整数, |小| ...