Linux 的字符转换库: GLIBC iconv函数组.
char str[ ]中存储的是“中文"的UTF-8编码
wchar_t wstr[ ]中存放的是“中文"的Unicode码值
比如将一个GBK 编码的文件转换成UTF-8编码: iconv -f GBK -t UTF-8 file1 -o file2
其中的参数的意义表示
-f From 某个编码-l, --list 列举所有已知的字符集-t To 某个编码-o 输出到文件
--verbose 打印进度信息
-?, --help 给出该系统求助列表
--usage 给出简要的用法信息
对于Unicode,Windows支持了它的三种编码方式,一种是小尾编码(Unicode),一种是大尾编码(BigEndianUnicode),一种是UTF-8编码。
我们可以从文件的头部来区分一个文件是属于哪种编码。
当头部开始的两个字节为 FF FE时,是Unicode的小尾编码;
当头部的两个字节为FE FF时,是Unicode的大尾编码;
当头部两个字节为EF BB时,是Unicode的UTF-8编码;
当它不为这些时,则是ANSI编码。
判断文件编码方式:
linux下:
1. LC_COLLATE
定义该环境的排序和比较规则
2. LC_CTYPE
用于字符分类和字符串处理,控制所有字符的处理方式,包括字符编码,字符是单字节还是多字节,如何打印等。是最重要的一个环境变量。
3. LC_MONETARY
货币格式
4. LC_NUMERIC
非货币的数字显示格式
5. LC_TIME
时间和日期格式
6. LC_MESSAGES
提示信息的语言。另外还有一个LANGUAGE 参数,它与LC_MESSAGES 相似,但如果该参数一旦设置,则LC_MESSAGES 参数就会失效。LANGUAGE 参数可同时设置多种语言信息,如LANGUANE="zh_CN.GB18030:zh_CN.GB2312:zh_CN" 。
7. LANG
LC_* 的默认值,是最低级别的设置,如果LC_* 没有设置,则使用该值。类似于 LC_ALL 。
8. LC_ALL
它是一个宏,如果该值设置了,则该值会覆盖所有LC_* 的设置值。注意,LANG 的值不受该宏影响。
一个例子:
设置前,使用默认locale
[root@db-wanggaofei ~]# export LC_ALL=zh_CN.GBK
[root@db-wanggaofei ~]# locale
"C" 是系统默认的locale ,"POSIX" 是"C" 的别名。所以当我们新安装完一个系统时,默认的locale 就是C 或POSIX 。
修改系统文件方式:
修改 /etc/sysconfig/i18n 文件,如
LANG="en_US.UTF-8",xwindow会显示英文界面,
LANG="zh_CN.GB18030",xwindow会显示中文界面。
还有一种方法 cp /etc/sysconfig/i18n $HOME/.i18n
修改 $HOME/.i18n 文件,如
LANG="en_US.UTF-8",xwindow会显示英文界面,
LANG="zh_CN.GB18030",xwindow会显示中文界面。
这样就可以改变个人的界面语言,而不影响别的用户
修改后的/etc/sysconfig/i18n 文件为:
LANG="en_US.UTF-8"
SUPPORTED="zh_CN.GB18030:zh_CN:zh:en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"
LC_ALL="en_US.UTF-8"
export LC_ALL
设置完毕后重启或者用rc.local使生效
或修改登录用户的.bash_profile文件加入
export LANG=zh_CN.GB18030
export LANGUAGE=zh_CN.GB18030:zh_CN.GB2312:zh_CN
或者:
默认为utf8,如出现乱码可设置为GBK
手动更改配置文件的命令:
shell> vi /etc/sysconfig/i18n
将LANG="zh_CN.UTF-8"修改为:
LANG="zh_CN.GBK"
保存并关闭,运行下面的命令使配置生效:
shell> source /etc/sysconfig/i18n
将终端字符编码显示为简体中文:
shell> vi /etc/profile.d/lang.sh
添加下面这行:export LC_ALL=zh_CN.GBK
shell> source /etc/profile.d/lang.sh
GB2312字集是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个。
iconv函数族有三个函数,原型如下:
(1) iconv_t iconv_open( const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。返回cd
以下四种情况不能完成转换:
输入含无效的多字节序列。 errno设置为 EILSEQ并返回(size_t)(-1)。 *inbuf指向无效序列的最左端。
输入的字节序列已经全部被转换过,也就是 *inbytesleft减少至0。此时, iconv返回本次调用中完成转换的数目(可逆的转换不计入)。
输入含不完整多字节序列。此时, errno设置为 EINVAL并返回(size_t)(-1)。 *inbuf指向不完整多字节序列的最左端。输出缓存区没有足够空间。此时,它将 errno设置为 E2BIG并返回(size_t)(-1)。
此函数用于关闭转换句柄,释放资源。
(4) int iconvctl (iconv_t cd , int request, void * argument);
ICONV_GET_TRANSLITERATE
argument类型应是int*,字译功能已打开为1,反之为0。
ICONV_SET_TRANSLITERATE
argument类型应是const int*,指向一个int值。非0将打开字译功能,0则关闭。
ICONV_GET_DISCARD_ILSEQ
argument类型应是int*,“忽略无效序列并继续转换”功能已打开为1,反之为0。
返回值: 成功,iconvctl函数返回0。出错时,它修改errno并返回(size_t)(-1)。
出现以下错误:EINVAL request的值无效。
iconv_t cd;
char *pin = in;
char *pout = out;
int inLen_ = inlen + 1;
int outLen_ = outlen;
cd = iconv_open( "GB2312", "UTF-8" );
if (cd == (iconv_t)-1)
printf("iconv_open false");
iconv( cd, &pin, (size_t*)&inLen_, &pout, (size_t*)&outLen_ );iconv_close(cd);
Windows CE 本身就是使用Unicode的一种操作系统,完全不支持ANSI Windows函数
Windows 98 只支持ANSI,只能为ANSI开发应用程序。
Microsoft公司将COM从16位Windows转换成Win32时,公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。
//#include "stdafx.h"#include <stdio.h>#include <windows.h>#include <locale.h>void WideToAnsi(WCHAR wszBuffer[],char pszBuffer[]){do{int nLen = WideCharToMultiByte(CP_ACP, 0, wszBuffer, -1, NULL, 0, NULL, NULL);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}nLen = WideCharToMultiByte(CP_ACP, 0, wszBuffer, -1, pszBuffer, nLen, NULL, NULL);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}} while (false);}void AnsiToWide(char szBuffer[],WCHAR pwszBuffer[]){do{int nLen = MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, NULL, 0);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}nLen = MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, pwszBuffer, nLen);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}} while (false);}void WideToUTF8(WCHAR pwszBuffer[],char pszBuffer[]){do{int nLen = WideCharToMultiByte(CP_UTF8, 0, pwszBuffer, -1, NULL, 0, NULL, NULL);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}WideCharToMultiByte(CP_UTF8, 0, pwszBuffer, -1, pszBuffer, nLen, NULL, NULL);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}} while (false);}void UTF8ToWide(char pszBuffer[],WCHAR wszBuffer[]){do{printf("utf8:%s\n",pszBuffer);int nLen = MultiByteToWideChar(CP_UTF8, 0, pszBuffer, -1, NULL, 0);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}nLen = MultiByteToWideChar(CP_UTF8, 0, pszBuffer, -1, wszBuffer, nLen);if(nLen == 0){printf("errorCode = %d\n", GetLastError());break;}} while (false);}void AnsiToUTF8(char szBuffer[],WCHAR pwszBuffer[],char pszBuffer[]){AnsiToWide(szBuffer,pwszBuffer);//多字节szBuffer转宽字节pwszBufferWideToUTF8(pwszBuffer,pszBuffer);//宽字节pwszBuffer转多字节pszBuffer}void UTF8ToAnsi(char szBuffer[],WCHAR pwszBuffer[],char pszBuffer[]){UTF8ToWide(szBuffer,pwszBuffer);WideToAnsi(pwszBuffer,pszBuffer);}int lcl_GetTextEncode(char* strTxtPath){int nType = -1;FILE *pFile = NULL;pFile = fopen(strTxtPath,"rt+");if (NULL == pFile){printf("loser");}//这里要注意是用unsigned char,不然的话读取到的数据会因为溢出而无法正确判断unsigned char* chFileFlag = new unsigned char[3];fread(chFileFlag, 1, 3, pFile);if(chFileFlag[0] == 0xEF && chFileFlag[1] == 0xBB && chFileFlag[2] == 0xBF)nType = 1;//UTF-8else if (chFileFlag[0] == 0xFF && chFileFlag[1] == 0xFE)nType = 2;//Unicodeelse if (chFileFlag[0] == 0xFE && chFileFlag[1] == 0xFF)nType = 3;//Unicode big endian textelsenType = 4;//ASCIIfclose(pFile);delete chFileFlag;return nType;}int main(){setlocale(LC_ALL, "chs"); // 这里设置locale是为了wprintf能正确的输出宽字符类型的中文int ret = 100;ret = lcl_GetTextEncode("wolegequ.TXT");//获取文件的编码方式char szFrom[32] = "殷翔";WCHAR *pwszTemp = new WCHAR[32];//typedef unsigned short WCHAR; 短整型两个字节char *pszTo = new char[32];AnsiToUTF8(szFrom,pwszTemp,pszTo);UTF8ToAnsi(pszTo,pwszTemp,szFrom);wprintf(L"pwszTemp = %s\n", pwszTemp);delete []pwszTemp;delete []pszTo;return 0;}
0000 - 007F 0xxxxxxx 单字节模板
0080 - 07FF 110xxxxx 10xxxxxx 双字节模板
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx 三字节模板
6C49写成二进制是:0110 1100 0100 1001, 将这个比特流按三字节模板的分段方法分为0110 110001 001001,依次代替模板中的x,得到:1110-0110 10-110001 10-001001,即E6 B1 89,这就是其UTF8的编码。
aa 1010 1010
cd 1100 1101
a8 1010 1000