中文转unicode问题
时间:2010-07-25
来源:互联网
- char *utf82ascii( unsigned char *utf8, unsigned short length, char *buf )
- {
- int i = 0;
- unsigned short a;
- unsigned char b;
- char *p = buf;
- unsigned char t[ 2 ];
- do
- {
- if( 0xe0 == ( *utf8 & 0xf0 ) &&
- 0x80 == ( *( utf8 + 1 ) & 0xc0 ) &&
- 0x80 == ( *( utf8 + 2 ) & 0xc0 ) )
- {
- //3个字节
- b = *utf8;
- b &= 0x0f;
- a = b;
-
- a <<= 6;
- b = *( utf8 + 1 );
- b &= 0x3f;
- a |= b;
-
- a <<= 6;
- b = *( utf8 + 2 );
- b &= 0x3f;
- a |= b;
-
- t[ 0 ] = ( a >> 8 ) & 0xff;
- t[ 1 ] = ( a & 0xff );
- u2s( t, 2, p );
-
- p += 2;
-
- i += 3;
- utf8 += 3;
- }
- else if ( 0xc0 == ( *utf8 & 0xe0 ) &&
- 0x80 == ( *( utf8 + 1 ) & 0xc0 ) )
- {
- //2个字节
- b = *utf8;
- b &= 0x1f;
- a = b;
-
- a <<= 6;
- b = *( utf8 + 1 );
- b &= 0x3f;
- a |= b;
-
- t[ 0 ] = ( a >> 8 ) & 0xff;
- t[ 1 ] = ( a & 0xff );
- u2s( t, 2, p );
-
- p += 2;
-
- i += 2;
- utf8 += 2;
- }
- else
- {
- //1个字节
- *( p++ ) = *( utf8++ );
-
- i++;
- }
- } while ( i < length );
- *p = 0;
-
- return buf;
- }
作者: jd808 发布时间: 2010-07-25
不是有个叫什么mbtocs和cstomb的么,多此一举~
作者: folklore 发布时间: 2010-07-25
1、 GB2312 编码到Unicode 编码的转换
在 Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。所以首先需要把 GB2312 编码的字符串转换到 Unicode编码的字符串。GB2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。(注:我没有仔细看过GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。在linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多):
1)、用 mbstowcs () 函数。就是多字节编码到宽字符的转换。我试过它,可以正确的转换,但是这个函数可能不是很可靠。
2)、用 GB2312 à Unicode 的转换表,手动查表转换。网上有这样的转换表,你需要对每一个GB2312字符,根据它是中文字符还是英文字符,分别转换。
3)、用 iconv () 函数。这可能是linux上的标准的方法,不仅可以转换GB2312到Unicode,还可以在任意的两种编码之间转换(前提是linux系统要支持这些编码)。
首先要用 iconv_open(), 打开一个转换句柄,指定两种转换前的编码和转换后的编码。
然后用 icnov() 作转换。最后用 iconv_close()关闭句柄,释放资源。
#include <iconv.h>
#define BUFLEN 200
char inbuf[BUFLEN];
char outbuf[BUFLEN];
char* pin = inbuf;
char* pout = outbuf;
…打开文件,读入GB2312数据到inbuf,数据长度为 len
int inleft = len;
int outleft = BUFLEN;
iconv_t cd;
if((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1)
return –1;
if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1)
return –1;
iconv_close(cd);
使用 iconv () 时,需要注意参数的使用,inleft 是输入缓冲区数据数据长度,outleft是输出缓冲区大小。(需要保证输出缓冲区足够大)。
转换以后,outleft 是outbuf中空闲空间的大小,所以 BUFLEN-outleft 才是真正的Unicode数据长度。
注意:不论是GB2312编码,还是Unicode编码,在内存中都是一些字节序列,所以我们可以统一用 类型为 char(或者unsigned char)的字符数组来保存。所以,BUFLEN-outleft 是 字符(char)个数,而不是Unicode字符个数。
2、 Unicode 编码到 16-bit 编码的转换
在得到 Unicode编码以后,还需要转换到 PDU 的16-bit 编码,才可以正确的发送。在这个转换过程中,需要注意两点:
1)、Unicode 编码最开始的 0xFEFF标志要被去除,在0xFEFF之后的内容,才是真正的Unicode字符。(至于为什么有这个0xfeff标志,知道的朋友告诉我一声,呵呵)。
2)、Unicode 是双字节字符,由于我的系统是小端字节序(little-endian),也就是说,在存储的时候,是先低位,后高位,例如“中”的Unicode编码是 0x4E2D,存储的时候是 2D4E,在转换到 16-bit编码的时候,要注意这个顺序的不同。当然,如果你的系统是大端字节序(big-endian),那么就不用这样做了。
OK,关于如何将 0x4E2D 的Unicode编码转换到 “4E2D” 的16-bit编码,我就不多写了。
3、正确计算16-bit 编码的消息体长度
4、正确设置 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP
在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的设置正确与否,对能否发送 Unicode 至关重要。根据协议规范以及我的调试结果,以上几个标志的正确设置分别为(都是16进制):
First-Octet : 11
TP-MR : 00
TP-PID : 00
TP-DCS : 08 (编码方式,16-bit)
TP-VP : A7
文章转载自网管网:http://www.bitscn.com/os/linuxbc/200701/97727.html
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
MBSTOWCS
Section: Linux Programmer's Manual (3)
Updated: 1999-07-25
Index JM Home Page roff page
--------------------------------------------------------------------------------
名前
mbstowcs - マルチバイト文字列をワイド文字列に変換する
書式
#include <stdlib.h>
size_t mbstowcs(wchar_t *dest, const char *src, size_t n);
説明
dest が NULL ポインターでなければ mbstowcs() 関数はマルチバイト文字列 *src を dest から始まるワイド文字列に変換する。dest には最大で n 文字のワイド文字が書き込まれる。変換は初期状態で開始され、以下の三つのいずれかの条件で停止する:
1.
不正なマルチバイト列に遭遇した。この場合には (size_t) -1 を返す。
2.
n 文字の Laq\0aq 以外のワイド文字を dest に格納した場合。この場合は *src が次に変換されるマルチバイト列を指すようにして、 dest に書き込まれたワイド文字の数を返す。しかしこの指している場所のシフト状態は失われる。
3.
マルチバイト文字列が終端の aq\0aq まで含めて完全に変換された場合。この場合は終端の Laq\0aq 文字を除いて dest に書き込まれた文字数を返す。
プログラマーは dest に最低でも n ワイド文字を書き込むことができる空間があることを保証しなければならない。
dest が NULL の場合、n は無視され、上記と同様の変換が行われるが、変換されたワイド文字はメモリに書き込まれず、変換先の上限が存在しない。
上記の 2. の場合を避けるためにプログラマーは n が mbstowcs(NULL,src,0)+1 以上であることを保証すべきである。
返り値
mbstowcs() 関数はワイド文字列に変換完了したワイド文字の数を返す。終端のナルワイド文字は含まない。不正なマルチバイト列に遭遇した場合には (size_t) -1 を返す。
準拠
C99.
注意
mbstowcs() の動作は現在のロケールの LC_CTYPE カテゴリに依存している。
mbsrtowcs(3) 関数は同じ機能のより良いインターフェースを提供する。
関連項目
mbsrtowcs(3)
--------------------------------------------------------------------------------
Index
名前
書式
説明
返り値
準拠
注意
関連項目
--------------------------------------------------------------------------------
This document was created by man2html, using the manual pages.
Time: 03:26:48 GMT, April 25, 2010
在 Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。所以首先需要把 GB2312 编码的字符串转换到 Unicode编码的字符串。GB2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。(注:我没有仔细看过GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。在linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多):
1)、用 mbstowcs () 函数。就是多字节编码到宽字符的转换。我试过它,可以正确的转换,但是这个函数可能不是很可靠。
2)、用 GB2312 à Unicode 的转换表,手动查表转换。网上有这样的转换表,你需要对每一个GB2312字符,根据它是中文字符还是英文字符,分别转换。
3)、用 iconv () 函数。这可能是linux上的标准的方法,不仅可以转换GB2312到Unicode,还可以在任意的两种编码之间转换(前提是linux系统要支持这些编码)。
首先要用 iconv_open(), 打开一个转换句柄,指定两种转换前的编码和转换后的编码。
然后用 icnov() 作转换。最后用 iconv_close()关闭句柄,释放资源。
#include <iconv.h>
#define BUFLEN 200
char inbuf[BUFLEN];
char outbuf[BUFLEN];
char* pin = inbuf;
char* pout = outbuf;
…打开文件,读入GB2312数据到inbuf,数据长度为 len
int inleft = len;
int outleft = BUFLEN;
iconv_t cd;
if((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1)
return –1;
if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1)
return –1;
iconv_close(cd);
使用 iconv () 时,需要注意参数的使用,inleft 是输入缓冲区数据数据长度,outleft是输出缓冲区大小。(需要保证输出缓冲区足够大)。
转换以后,outleft 是outbuf中空闲空间的大小,所以 BUFLEN-outleft 才是真正的Unicode数据长度。
注意:不论是GB2312编码,还是Unicode编码,在内存中都是一些字节序列,所以我们可以统一用 类型为 char(或者unsigned char)的字符数组来保存。所以,BUFLEN-outleft 是 字符(char)个数,而不是Unicode字符个数。
2、 Unicode 编码到 16-bit 编码的转换
在得到 Unicode编码以后,还需要转换到 PDU 的16-bit 编码,才可以正确的发送。在这个转换过程中,需要注意两点:
1)、Unicode 编码最开始的 0xFEFF标志要被去除,在0xFEFF之后的内容,才是真正的Unicode字符。(至于为什么有这个0xfeff标志,知道的朋友告诉我一声,呵呵)。
2)、Unicode 是双字节字符,由于我的系统是小端字节序(little-endian),也就是说,在存储的时候,是先低位,后高位,例如“中”的Unicode编码是 0x4E2D,存储的时候是 2D4E,在转换到 16-bit编码的时候,要注意这个顺序的不同。当然,如果你的系统是大端字节序(big-endian),那么就不用这样做了。
OK,关于如何将 0x4E2D 的Unicode编码转换到 “4E2D” 的16-bit编码,我就不多写了。
3、正确计算16-bit 编码的消息体长度
4、正确设置 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP
在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的设置正确与否,对能否发送 Unicode 至关重要。根据协议规范以及我的调试结果,以上几个标志的正确设置分别为(都是16进制):
First-Octet : 11
TP-MR : 00
TP-PID : 00
TP-DCS : 08 (编码方式,16-bit)
TP-VP : A7
文章转载自网管网:http://www.bitscn.com/os/linuxbc/200701/97727.html
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
MBSTOWCS
Section: Linux Programmer's Manual (3)
Updated: 1999-07-25
Index JM Home Page roff page
--------------------------------------------------------------------------------
名前
mbstowcs - マルチバイト文字列をワイド文字列に変換する
書式
#include <stdlib.h>
size_t mbstowcs(wchar_t *dest, const char *src, size_t n);
説明
dest が NULL ポインターでなければ mbstowcs() 関数はマルチバイト文字列 *src を dest から始まるワイド文字列に変換する。dest には最大で n 文字のワイド文字が書き込まれる。変換は初期状態で開始され、以下の三つのいずれかの条件で停止する:
1.
不正なマルチバイト列に遭遇した。この場合には (size_t) -1 を返す。
2.
n 文字の Laq\0aq 以外のワイド文字を dest に格納した場合。この場合は *src が次に変換されるマルチバイト列を指すようにして、 dest に書き込まれたワイド文字の数を返す。しかしこの指している場所のシフト状態は失われる。
3.
マルチバイト文字列が終端の aq\0aq まで含めて完全に変換された場合。この場合は終端の Laq\0aq 文字を除いて dest に書き込まれた文字数を返す。
プログラマーは dest に最低でも n ワイド文字を書き込むことができる空間があることを保証しなければならない。
dest が NULL の場合、n は無視され、上記と同様の変換が行われるが、変換されたワイド文字はメモリに書き込まれず、変換先の上限が存在しない。
上記の 2. の場合を避けるためにプログラマーは n が mbstowcs(NULL,src,0)+1 以上であることを保証すべきである。
返り値
mbstowcs() 関数はワイド文字列に変換完了したワイド文字の数を返す。終端のナルワイド文字は含まない。不正なマルチバイト列に遭遇した場合には (size_t) -1 を返す。
準拠
C99.
注意
mbstowcs() の動作は現在のロケールの LC_CTYPE カテゴリに依存している。
mbsrtowcs(3) 関数は同じ機能のより良いインターフェースを提供する。
関連項目
mbsrtowcs(3)
--------------------------------------------------------------------------------
Index
名前
書式
説明
返り値
準拠
注意
関連項目
--------------------------------------------------------------------------------
This document was created by man2html, using the manual pages.
Time: 03:26:48 GMT, April 25, 2010
作者: folklore 发布时间: 2010-07-25
- #include <stdio.h>
- #include <stdlib.h>
- #include <strings.h>
- #include <string.h>
- #include <unistd.h>
- #include <iconv.h>
- int CodeChange(char *p_inBuf, char *p_OutBuf, int *p_OutSize, const char *p_inCode, const char *p_OutCode);
- int main()
- {
- char *p_inBuf;
- p_inBuf="妈的的这么难弄啊";
- char p_OutBuf[30];
- CodeChange(p_inBuf,p_OutBuf,"30","gb2312","unicode");
- }
-
-
- /*UTF8<->GBK*/
- int CodeChange(char *p_inBuf, char *p_OutBuf, int *p_OutSize, const char *p_inCode, const char *p_OutCode)
- {
- iconv_t cd;
- int inLen;
-
- inLen = strlen(p_inBuf);
-
- if ((cd = iconv_open(p_OutCode, p_inCode)) == (iconv_t) -1)
- {
- return - 1;
- }
-
- if (iconv(cd, &p_inBuf, (size_t*) &inLen, &p_OutBuf, (size_t*)p_OutSize) == (size_t) -1)
- {
- iconv_close(cd);
- return - 1;
- }
-
- iconv_close(cd);
-
- return 0;
- }
int *p_OutSize这个参数怎么设置也不正确
并且还报了
- ./test.c:13: 警告:传递参数 3 (属于 ‘CodeChange’)时在不兼容的指针类型间转换
- ./test: In function `_start':
- (.text+0x0): multiple definition of `_start'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.text+0x0): first defined here
- ./test:(.rodata+0x0): multiple definition of `_fp_hw'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.rodata+0x0): first defined here
- ./test: In function `_fini':
- (.fini+0x0): multiple definition of `_fini'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o:(.fini+0x0): first defined here
- ./test:(.rodata+0x4): multiple definition of `_IO_stdin_used'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.rodata.cst4+0x0): first defined here
- ./test: In function `__data_start':
- (.data+0x0): multiple definition of `__data_start'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.data+0x0): first defined here
- ./test:(.rodata+0x8): multiple definition of `__dso_handle'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o:(.rodata+0x0): first defined here
- ./test: In function `main':
- (.text+0xd4): multiple definition of `main'
- /tmp/ccQYjhoz.o:test.c:(.text+0x0): first defined here
- /usr/bin/ld: Warning: size of symbol `main' changed from 76 in /tmp/ccQYjhoz.o to 107 in ./test
- ./test: In function `_init':
- (.init+0x0): multiple definition of `_init'
- /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o:(.init+0x0): first defined here
- /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o:(.dtors+0x0): multiple definition of `__DTOR_END__'
- ./test:(.dtors+0x4): first defined here
- collect2: ld 返回 1
作者: jd808 发布时间: 2010-07-25
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28