2005-8-26 09:37
99大话王
<!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->SMS中用Unicode编码发送中文<br /><br />SMS是由Esti 所制定的一个规范(GSM 03.40 和 GSM 03.38)。有两种方式来发送和接收SMS消息:文本模式或者PDU(protocol description unit)模式。文本模式只能发送普通的ASCII字符,而要发送图片、铃声、其它编码的字符(如中文)就必须采用PDU模式。 <br />PDU模式中,可以采用三种编码方式来编码要发送的内容,分别是 7-bit编码、8-bit编码、16-bit编码。7-bit编码用于发送普通的ASCII字符;8-bit编码通常用于发送数据消息,比如图片和铃声等;而16-bit编码用于发送Unicode字符。在这三种编码方式下,可以发送的最大字符数分别是 160、 140、 70。 <br />若要发送中文(或日文等),必须采用PDU模式的Unicode编码方式。 <br />我最近参与了一个在linux下收发短信的项目。其中,需要实现中文的发送和接收。由于原来没有中文编码、Unicode编码的经验,所以查了一些资料,也在一些论坛上提了一些问题。现在把它整理出来,希望对以后再做类似项目的朋友有个帮助。我写的比较简单,关于PDU的规范,可以看这里:http://www.ascend-tech.com.cn/sustain/SMS_PDU-mode.pdf ,或者去wavecom的网站上找找看。 <br /><br />1、 GB2312 编码到Unicode 编码的转换 <br /><br />在 Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。所以首先需要把 GB2312 编码的字符串转换到 Unicode编码的字符串。GB2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。(注:我没有仔细看过GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。在linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多): <br />1)、用 mbstowcs () 函数。就是多字节编码到宽字符的转换。我试过它,可以正确的转换,但是这个函数可能不是很可靠。 <br /><br />2)、用 GB2312 à Unicode 的转换表,手动查表转换。网上有这样的转换表,你需要对每一个GB2312字符,根据它是中文字符还是英文字符,分别转换。 <br /><br />3)、用 iconv () 函数。这可能是linux上的标准的方法,不仅可以转换GB2312到Unicode,还可以在任意的两种编码之间转换(前提是linux系统要支持这些编码)。 <br />首先要用 iconv_open(), 打开一个转换句柄,指定两种转换前的编码和转换后的编码。 <br />然后用 icnov() 作转换。最后用 iconv_close()关闭句柄,释放资源。 <br /><br /><br /><br />#include <iconv.h> <br /><br />#define BUFLEN 200 <br />char inbuf[BUFLEN]; <br />char outbuf[BUFLEN]; <br />char* pin = inbuf; <br />char* pout = outbuf; <br /><br />…打开文件,读入GB2312数据到inbuf,数据长度为 len <br /><br />int inleft = len; <br />int outleft = BUFLEN; <br /><br />iconv_t cd; <br />if((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1) <br />return –1; <br />if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1) <br />return –1; <br />iconv_close(cd); <br /><br />使用 iconv () 时,需要注意参数的使用,inleft 是输入缓冲区数据数据长度,outleft是输出缓冲区大小。(需要保证输出缓冲区足够大)。 <br />转换以后,outleft 是outbuf中空闲空间的大小,所以 BUFLEN-outleft 才是真正的Unicode数据长度。 <br />注意:不论是GB2312编码,还是Unicode编码,在内存中都是一些字节序列,所以我们可以统一用 类型为 char(或者unsigned char)的字符数组来保存。所以,BUFLEN-outleft 是 字符(char)个数,而不是Unicode字符个数。 <br /><br /><br />2、 Unicode 编码到 16-bit 编码的转换 <br /><br />在得到 Unicode编码以后,还需要转换到 PDU 的16-bit 编码,才可以正确的发送。在这个转换过程中,需要注意两点: <br />1)、Unicode 编码最开始的 0xFEFF标志要被去除,在0xFEFF之后的内容,才是真正的Unicode字符。(至于为什么有这个0xfeff标志,知道的朋友告诉我一声,呵呵)。 <br /><br />2)、Unicode 是双字节字符,由于我的系统是小端字节序(little-endian),也就是说,在存储的时候,是先低位,后高位,例如“中”的Unicode编码是 0x4E2D,存储的时候是 2D4E,在转换到 16-bit编码的时候,要注意这个顺序的不同。当然,如果你的系统是大端字节序(big-endian),那么就不用这样做了。 <br /><br />OK,关于如何将 0x4E2D 的Unicode编码转换到 “4E2D” 的16-bit编码,我就不多写了。 <br /><br /><br />3、正确计算16-bit 编码的消息体长度 <br /><br />4、正确设置 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP <br /><br />在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的设置正确与否,对能否发送 Unicode 至关重要。根据协议规范以及我的调试结果,以上几个标志的正确设置分别为(都是16进制): <br />First-Octet : 11 <br />TP-MR : 00 <br />TP-PID : 00 <br />TP-DCS : 08 (编码方式,16-bit) <br />TP-VP : A7 <br /><br />经过以上步骤,已经可以做到发送中文字符了。 <br />希望这篇文档,能为准备在linux下做短信开发的朋友提供一些帮助。 <br /><!--QuoteEnd--></div><!--QuoteEEnd-->
2005-8-26 09:51
99大话王
我想把<span style='color:red'>一</span>个汉字转unicode的代码,在Linux下不成功 <!--emo&:cry:--><img src='style_emoticons/default/cry_smile.gif' border='0' style='vertical-align:middle' alt='cry_smile.gif' /><!--endemo--> <br />iconv返回-1 <!--emo&:(--><img src='style_emoticons/default/sad.gif' border='0' style='vertical-align:middle' alt='sad.gif' /><!--endemo--> <br />谁有过这方面的经验,谢谢指点<br /><br /><!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--> wchar_t Gb2312ToUnicode(char *pStr)<br /> {<br /> static wchar_t wch = 0;<br /> wch = 0;<br />#ifdef WIN32<br /> ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pStr, 2, &wch, 1);<br />#else<br /> bool iconv_good = false;<br /> do<br /> {<br /> iconv_t cd = iconv_open("gb2312", "unicode");<br /> if (0 == cd)<br /> {<br /> cout << "0 == iconv_open" << endl;<br /> break;<br /> }<br /><br /> char *pin = pStr;<br /> size_t inlen = 2;<br /><br /> char *outbuf = (char*)&wch;<br /> char *pout = outbuf;<br /> size_t outlen = 2;<br /><br /> char buf[10];<br /> outbuf = buf;<br /> outlen = 10;<br /><br /> if (-1 == iconv(cd, &pin, &inlen, &pout, &outlen))<br /> {<br /> cout << "-1 == iconv" << endl;<br /> break;<br /> }<br /> iconv_close(cd);<br /> iconv_good = true;<br /> }<br /> while (false);<br /> if (true != iconv_good)<br /> {<br /> cout << "iconv_good = " << iconv_good << endl;<br /><br /> /*<br /> int ch = *pStr;<br /> int ch2 = *(pStr + 1);<br /> int c = ( ch2 | (ch << 8) );<br /> wch = c;<br /> */<br /> }<br />#endif<br /> cout << "wch = " << wch << endl;<br /> return wch;<br /> }<br /><!--c2--></div><!--ec2-->
2005-8-26 10:14
wcp2004
学习中,不错!
2005-8-26 14:52
无双
unicode的iconv 参数应该是"UCS-2"吧 改下看看
2005-8-26 17:43
99大话王
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--><br />// &acute;ú&Acirc;&euml;×&ordf;&raquo;&raquo;&sup2;&Ugrave;×÷&Agrave;à<br />class CodeConverter<br />{<br />private:<br /> iconv_t cd;<br />public:<br /> // &sup1;&sup1;&Ocirc;ì<br /> CodeConverter(const char *from_charset,const char *to_charset)<br /> {<br /> cd = iconv_open(to_charset,from_charset);<br /> }<br /> <br /> // &Icirc;&ouml;&sup1;&sup1;<br /> ~CodeConverter()<br /> {<br /> iconv_close(cd);<br /> }<br /> <br /> // ×&ordf;&raquo;&raquo;&Ecirc;&auml;&sup3;&ouml;<br /> int convert(char *inbuf,int inlen,char *outbuf,int outlen)<br /> {<br /> char **pin = &inbuf;<br /> char **pout = &outbuf;<br /> <br /> memset(outbuf,0,outlen);<br /> //return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);<br /> int ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);<br /> if (-1 == ret) printf ("iconv: %m\n");<br /> return ret;<br /> }<br />};<br /><!--c2--></div><!--ec2--><br />成功了<br />void main()<br />{<br />#define OUTLEN 255<br /> char* p1 = "超级女生";<br /> char p2[] = {*p1, *(p1 + 1), 0};<br /> char out[OUTLEN];<br /> CodeConverter cc2 = CodeConverter("gb2312","unicode");<br /> int n = cc2.convert(p1, strlen(p1), out,OUTLEN);<br />}<br />
2005-8-29 09:30
无双
哦 原来你第一次传入的参数是指针地址 所以出问题
2006-9-30 13:20
triphop
如果想详细学习一下SMS的话,建议看看3GPP 24.011协议
不过从我个人角度来说,SMS协议应该是非常简单的协议。
从终端和短信中心的交互流程上讲,也是非常简单。
就是几个CP-DATA, CP-ACK
页:
[1]
Powered by Discuz! Archiver 5.5.0
© 2001-2006 Comsenz Inc.