+ -
当前位置:首页 → 问答吧 → 中文转unicode问题

中文转unicode问题

时间:2010-07-25

来源:互联网

  1. char *utf82ascii( unsigned char *utf8, unsigned short length, char *buf )
  2. {
  3.     int i = 0;
  4.     unsigned short a;
  5.     unsigned char b;
  6.     char *p = buf;
  7.     unsigned char t[ 2 ];
  8.     do
  9.     {
  10.         if( 0xe0 == ( *utf8 & 0xf0 ) &&
  11.             0x80 == ( *( utf8 + 1 ) & 0xc0 ) &&
  12.             0x80 == ( *( utf8 + 2 ) & 0xc0 ) )
  13.         {
  14.             //3个字节
  15.             b = *utf8;
  16.             b &= 0x0f;
  17.             a = b;

  18.             a <<= 6;
  19.             b = *( utf8 + 1 );
  20.             b &= 0x3f;
  21.             a |= b;

  22.             a <<= 6;
  23.             b = *( utf8 + 2 );
  24.             b &= 0x3f;
  25.             a |= b;

  26.             t[ 0 ] = ( a >> 8 ) & 0xff;
  27.             t[ 1 ] = ( a & 0xff );
  28.             u2s( t, 2, p );

  29.             p += 2;

  30.             i += 3;
  31.             utf8 += 3;
  32.         }
  33.         else if ( 0xc0 == ( *utf8 & 0xe0 ) &&
  34.                 0x80 == ( *( utf8 + 1 ) & 0xc0 ) )
  35.         {
  36.             //2个字节
  37.             b = *utf8;
  38.             b &= 0x1f;
  39.             a = b;

  40.             a <<= 6;
  41.             b = *( utf8 + 1 );
  42.             b &= 0x3f;
  43.             a |= b;

  44.             t[ 0 ] = ( a >> 8 ) & 0xff;
  45.             t[ 1 ] = ( a & 0xff );
  46.             u2s( t, 2, p );

  47.             p += 2;

  48.             i += 2;
  49.             utf8 += 2;
  50.         }
  51.         else
  52.         {
  53.             //1个字节
  54.             *( p++ ) = *( utf8++ );

  55.             i++;
  56.         }
  57.     } while ( i < length );
  58.     *p = 0;

  59.     return buf;
  60. }
复制代码
在网上找到了这个函数,编译的时候发现   u2s( t, 2, p );这个无法编译,这个函数在哪里?哪位高手有更好的办法转换成unicode呢?

作者: 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

作者: folklore   发布时间: 2010-07-25

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <strings.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <iconv.h>
  7. int CodeChange(char *p_inBuf, char *p_OutBuf, int *p_OutSize, const char *p_inCode, const char *p_OutCode);
  8. int main()
  9. {
  10.         char *p_inBuf;
  11.         p_inBuf="妈的的这么难弄啊";
  12.         char p_OutBuf[30];
  13.         CodeChange(p_inBuf,p_OutBuf,"30","gb2312","unicode");
  14. }


  15. /*UTF8<->GBK*/
  16. int CodeChange(char *p_inBuf, char *p_OutBuf, int *p_OutSize, const char  *p_inCode, const char *p_OutCode)
  17. {
  18.     iconv_t cd;
  19.     int inLen;

  20.     inLen = strlen(p_inBuf);

  21.     if ((cd = iconv_open(p_OutCode, p_inCode)) == (iconv_t) -1)
  22.     {
  23.         return  - 1;
  24.     }

  25.     if (iconv(cd, &p_inBuf, (size_t*) &inLen, &p_OutBuf, (size_t*)p_OutSize) ==  (size_t) -1)
  26.     {
  27.         iconv_close(cd);
  28.         return  - 1;
  29.     }

  30.     iconv_close(cd);

  31.     return 0;
  32. }
复制代码
./test.c:13: 警告:传递参数 3 (属于 ‘CodeChange’)时在不兼容的指针类型间转换
int *p_OutSize这个参数怎么设置也不正确
并且还报了
  1. ./test.c:13: 警告:传递参数 3 (属于 ‘CodeChange’)时在不兼容的指针类型间转换
  2. ./test: In function `_start':
  3. (.text+0x0): multiple definition of `_start'
  4. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.text+0x0): first defined here
  5. ./test:(.rodata+0x0): multiple definition of `_fp_hw'
  6. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.rodata+0x0): first defined here
  7. ./test: In function `_fini':
  8. (.fini+0x0): multiple definition of `_fini'
  9. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o:(.fini+0x0): first defined here
  10. ./test:(.rodata+0x4): multiple definition of `_IO_stdin_used'
  11. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.rodata.cst4+0x0): first defined here
  12. ./test: In function `__data_start':
  13. (.data+0x0): multiple definition of `__data_start'
  14. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o:(.data+0x0): first defined here
  15. ./test:(.rodata+0x8): multiple definition of `__dso_handle'
  16. /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbegin.o:(.rodata+0x0): first defined here
  17. ./test: In function `main':
  18. (.text+0xd4): multiple definition of `main'
  19. /tmp/ccQYjhoz.o:test.c:(.text+0x0): first defined here
  20. /usr/bin/ld: Warning: size of symbol `main' changed from 76 in /tmp/ccQYjhoz.o to 107 in ./test
  21. ./test: In function `_init':
  22. (.init+0x0): multiple definition of `_init'
  23. /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o:(.init+0x0): first defined here
  24. /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o:(.dtors+0x0): multiple definition of `__DTOR_END__'
  25. ./test:(.dtors+0x4): first defined here
  26. collect2: ld 返回 1
复制代码
这些错误

作者: jd808   发布时间: 2010-07-25

相关阅读 更多