关于汉字字符串处理等问题,utf8方案(50分)

  • 主题发起人 主题发起人 JiYangTX
  • 开始时间 开始时间
J

JiYangTX

Unregistered / Unconfirmed
GUEST, unregistred user!
注意到在Delphi中定义
type Utf8String=type String;

所以在处理汉字等字符替换的时候先统统Utf8Encode,在StringReplace,在Utf8Decode
是不是就能实现较完美的处理而不出现乱码等现象?大家说说看法。
 
delphi 编码转换 unicode gbk big5
(转载)
[ 2006-03-23 15:39:23 | 作者: Admin ]
字体大小: 大 | 中 | 小
以下代码在DELPHI 7上调试通过,主要使用了api函数中MultiByteToWidechar

function UnicodeEncode(Str:string;CodePage:integer):WideString;
var
Len:integer;
begin
Len:=Length(Str)+1;
SetLength(Result,Len);
Len:=MultiByteToWideChar(CodePage,0,PChar(Str),-1,PWideChar(Result),Len);
SetLength(Result,Len-1); //end is #0
end;

function UnicodeDecode(Str:WideString;CodePage:integer):string;
var
Len:integer;
begin
Len:=Length(Str)*2+1; //one for #0
SetLength(Result,Len);
Len:=WideCharToMultiByte(CodePage,0,PWideChar(Str),-1,PChar(Result),Len,nil,nil);
SetLength(Result,Len-1);
end;

function Gb2Big5(Str:string):string;
begin
SetLength(Result,Length(Str));
LCMapString(GetUserDefaultLCID,LCMAP_TRADITIONAL_CHINESE,
PChar(Str),Length(Str),
PChar(Result),Length(Result));
Result:=UnicodeDecode(UnicodeEncode(Result,936),950);
end;

function Big52Gb(Str:string):string;
begin
Str:=UnicodeDecode(UnicodeEncode(Str,950),936);
SetLength(Result,Length(Str));
LCMapString(GetUserDefaultLCID,LCMAP_SIMPLIFIED_CHINESE,
PChar(Str),Length(Str),
PChar(Result),Length(Result));
end;

关键使用了UnicodeToUtf8这个函数
function Utf8Encode(const WS: WideString): UTF8String;
var
L: Integer;
Temp: UTF8String;
begin
Result := '';
if WS = '' then Exit;
SetLength(Temp, Length(WS) * 3); // SetLength includes space for null terminator
L := UnicodeToUtf8(PChar(Temp), Length(Temp)+1, PWideChar(WS), Length(WS));
if L > 0 then
SetLength(Temp, L-1)
else
Temp := '';
Result := Temp;
end; -
=======================
方法二:
后来想到了用Unicode编码,但该死的Delphi控件竟然不支持Unicode,后来在网上找到了Tnt控件,可以支持Unicode不过而项目已经差不多快好了,要大规模换控件是不可能的,就想到读一下源代码,看看Tnt控件是如何做到的。读完之后一阵绝望,Tnt控件几乎全用W结尾的API,连创建窗体都是用CreateWindowExW,那还有什么好话说呢,自己重做就不如全换Tnt控件
----------------------
Delphi: 将unicode码转换为汉字
Night @ 2004-12-01 21:12


function UnicodeToAnsi(SubUnicode: string):string; //将unicode码转换为汉字
var a:array[0..500] of char;
s1,s2:char;
substr1,substr2,s:string;
str:string;
i:integer;
begin
if length(SubUnicode) mod 4 = 0 then
Begin



str:='';
for i:=1 to length(SubUnicode) div 4 do
Begin
s:='';
substr1:=copy(SubUnicode,i*4-3,2);
substr2:=copy(SubUnicode,i*4-1,2);
s1:=chr(hextoint(substr1));
s2:=chr(hextoint(substr2));
s:=s+s2+s1;
strpcopy(a,s);
str:=str+copy(widechartostring(@(a[0])),1,2);
end;
result:=str;
end;
end;



function HexToInt(hex:string):cardinal;
const cHex='0123456789ABCDEF';
var mult,i,loop:integer;
begin
result:=0;
mult:=1;
for loop:=length(hex)downto 1 do
begin
i:=pos(hex[loop],cHex)-1;
if (i<0) then i:=0;
inc(result,(i*mult));
mult:=mult*16;
end;
end;
-----
tnt控件下载地址
tnt delphi unicode controls 版  本:
文件大小:314.7k
软件语言:简体中文
授权方式:免费版
相关链接:程序演示
开 发 商:本站搜集
运行环境:
添加时间:2006-01-13
发布人:本站搜集

本站搜集最近发布的资源:


留言通知我们。
*欢迎广大作者给我们提供源码以及使用说明。下载操作前请详细阅读[版权说明].
资源介绍:
完全解决了vcl控件不支持unicode的问题,让你开发国际化的程序变得更为高效,含源码。

地址:
http://www.ribaidu.org/codechinanet/resource/html/2006-01/13/131419.html
 
谢谢蓝叶菱的回复[:D]
期望更多的回复[8D]
 
话题2299582的标题是: gb2312怎样转换为UTF-8 (200分)
分类:局域网 / 通讯 shuaihu (2003-11-17 15:00:00)
嵌入式GSM短信息接口的软硬件设计
文章作者:马 潮
文章类型:设计应用 文章加入时间:2003年9月24日2:31
文章出处:单片机及嵌入式系统应用

--------------------------------------------------------------------------------




摘要:SMS短信息服务作为GSM网络的一种基本业务已得到越来越多的系统运营商和系统开发商的重视,以GSM网络作为数据无线传输网络,可以开发出多种前景极其乐观的各类应用。本文给出一个小型的嵌入式SMS中/英文短信息接口的设计,并详细讨论PDU模式的短信息格式和中文短信息软件解码的设计。

关键词:GSM SMS UTF-8 GB-2312 无线通信 无线数传 遥控 中文编码

引 言

  SMS(Short Message Service)短信息服务是GSM(Global System for Mobile Communication)系统中提供的一种GSM终端(手机)之间,通过服务中心(Service Center)进行文本信息收发的应用服务,其中服务中心完成信息的存储和转发功能。短信息服务作为GSM网络的一种基本业务,已得到越来越多的系统运营商和系统开发商的重视,基于这种业务的各种应用也蓬勃发展起来。以GSM网络作为数据无线传输网络,可以开发出多种前景极其乐观的各类应用,如无线数据的双向传送、无线远程检测和控制等。典型的应用有:变电站、电表、水塔、水库或环保监测点等监测数据的无线传输和无线自动警报;远程无线控制高压线路断电器、加热系统、防洪拦阻系统或其它机电系统的启动和关闭;车队交通管理和控制指挥系统;控制和监测香烟、食品和饮料自动售货机的运行状态和存货水平等等。

  由于GSM网络在全国范围内实现了联网和漫游,具有网络能力强的特点,用户无需另外组网,在极大提高网络覆盖范围的同时为客户节省了昂贵建网费用和维护费用。同时,它对用户的数量也没有限制,克服了传统的专网通信系统投资成本大,维护费用高,且网络监控的覆盖范围和用户数量有限的缺陷。比起传统的集群系统在无线网络覆盖上具有无法比拟的优势,加上GSM的SMS本身具备的数据传送功能,都使得这些应用得到迅速的普及。利用GSM短信息系统进行无线通信还具有双向数据传输功能,性能稳定,为远程数据传送和监控设备的通信提供了一个强大的支持平台。

1 SMS短信息的无线数传监视和控制

  通常情况,基于SMS短信息服务的无线数传监视和控制系统为一个点到多点的远程无线双向数据通信和控制系统,如图1所示。系统的中心点为数据或监控指挥中心,由计算机网络、数据库、电子地图和GSM通信接口组成。监控中心主要完成各种信息和数据的收发和整理:一方面,接收各个监控点上传的信息和数据,并把它们放入相应的数据库和分发给相应的监控计算机,以实现对各个监控点的监控和管理;另一个方面,监控中心响应监控计算机发出的对各个监控点的控制信息,并且把这些信息下发到相应的监控点上,从而达到对监控点设备进行控制的目的。

2 GSM无线通信控制终端

  GSM无线通信控制终端为一个MC3的嵌入式系统,具有如图2所示的测量、数据采集、控制、无线通信功能。GSM无线通信控制终端通过GSM网络和监控中心进行双向的信息传输。它将测量和采集到的数据信息传送到监控中心,同时接收监控中心的控制数据,对设备实施相应的控制。

3 GSM通信接口的硬件实现

  GSM无线通信控制终端的通信接口一般采用目前在市场上提供的可供二次开发的标准的GSM模块,如TC35、FALCOM、WISMO3等。这些通信模块都具备GSM无线通信的全部功能,并提供标准的UART串行接口,支持GSM 07.05所定义的AT命令集的指令。因此,MCU能非常方便地通过UART接口与GSM模块连接,并直接使用AT命令就可以方便简洁地实现短信息的收发、查寻和管理。

  在我们设计的GSM无线通信控制终端中,采用的GSM通信模块为FALCOM A2D,MCU使用的是Atmel公司的高速8位微控制器ATmage128。ATmega128芯片为64个引脚,内部集成了4K字节的RAM、4K字节的EEPROM、128K字节的Flash以及2个UART串行接口等。由于采用了高性能的MCU,省掉了大量的外围器件,如外扩RAM、ROM存储器等,使硬件结构大大简化,提高了系统的可靠性。系统的硬件框图如图3所示。

4 基于GSM通信的软件接口

  市场上提供的可供二次开发的标准的GSM模块都支持GSM 07.05所定义的AT命令集的指令。因此,MCU通过UART串行接口直接向GSM模块下发AT命令,就可以方便简洁地实现基于GSM的短信息SMS的收发、查寻和管理。表1列出了与SMS相关的一些常用的GSM AT指令。

表1 与SMS相关的常用GSM AT命令

AT指令 功 能

AT+CMGD 删除一条保存在SIM卡内的短信息
AT+CMGF 选择短信息格式:0为PDU方式:1为文本方式
AT+CMGL 列出SIM卡中的保存短信息
AT+CMGR 读取SIM卡中指定一条短信息的内容
AT+CMGS 发送一条短信息
AT+CSCA 设置短信息服务中心地址

  根据GSM 07.05的定义,SMS短信息的发送和接收模式共有三种:Block模式、基于AT命令的Text模式和基于AT命令的PDU模式。使用Block模式需要模块生产厂家提供驱动支持;而用于中英文短信息传送应使用PDU模式,只传送英文短信息(纯文本格式)使用Text模式。Text模式的短信息发送和接收比较简单,如不需要传送中文则最好采用Text模式发送和接收短信息。

  采用Text模式发送接收短信息的步骤分为初始化GSM模块、发送文本短信息和接收短信息。下面一段简单的程序给出一个示例:

PRINT "AT+CSCA=";Chr(34);"+8613800210500";Chr(34) ‘设置短信息中心号码

PRINT "AT+CMGF=1" ‘设置为Text模式

PRINT "AT+CMGS=";Chr(34);"13500123456";Chr(34) ‘发送一条短信息

PRINT "This is a test SMS";Chr(26)

PRINT "AT+CMGR=1" ‘读取收到的一条

‘短信息

.

.

.

  该程序使用BASCOM-AVR高级语言编写,其中PRINT语句的功能是通过URAT串行口发送字符串,Chr(34)代表ASCII字符(“),Chr(26) 代表ASCII字符(Ctrl-Z)。第一行语句设置短信息服务中心号码,即通过串口发送以下字符串: AT+CSCA= "+8613800210500",其中+8613800210500为上海地区中国移动的短信息服务中心号码。第二行语句设置短信息发送格式:AT+CMGF=1,其中1表示采用Text模式。第三和第四行语句发送一条短信息到控制中心,AT命令的格式为:AT+CMGS= "13500123456"<cr>This is a test SMS<^Z>,其中控制中心的号码为13500123456,短信息内容为“This is a test SMS”,确认控制字符为Ctrl-Z。第五行语句为读取一条收到的短信息内容:AT+CMGR=1,其中1表示收到的(在SIM卡中)第一条短信息。该指令发出后,如果GSM模块中有接收到的短信息,则从UART接口返回如下信息(具体AT命令格式请参考GSM 07.05):

  +CMGR: "REC UNREAD","+8613508485560",,"02/10/16,15:37:28+32"

xxxxxxxxxxxxxxxxxx (收到短信息的文本内容)

5 基于PDU模式的中文短信息接收

  发送和接收中文或中/英文混合的短信息必须采用PDU模式。根据GSM 07.05的定义,只要控制器通过UART接口向GSM模块下发AT命令,就可以直接读取收到的PDU模式的短信息:

  PRINT "AT+CMGF=0" ‘设置为PDU模式

  PRINT "AT+CMGR=1"‘读取接收的一条短信

‘息

在PDU模式下,GSM通信模块的回答格式为:

+CMGR: <stat>,,<length><CR><LF><pdu>

  其中: stat表示该条短信息的状态,通常为0(未读过,新的短信息)或1(已读过);

Length为十进制数,表示pdu数据长度减去短信息服务中心地址长度,单位为字节;

<CR><LF>为回车换行;

pdu为PDU模式的数据包。

  然后,要分析PDU数据包,根据PDU的数据格式将收到的中文信息和其它相关信息解析出来。

5.1 PDU数据包格式

  PDU数据包由两部分构成,短信息服务中心地址(SMSC address)和TPDU,表2为PDU数据包的格式,其中一个数据单元为一个字节。

  其中短信息服务中心号码、发送源号码、日期以及时间采用压缩BCD码表示,低位在前,高位在后。在本文的网络补充版(http://www.dpj.com.cn)中给出了通过读取短信息的AT命令(AT+CMGR=1)从GSM模块读到的一条PDU模式的短信息,并给出常见的数值与解释。

5.2 PDU模式的纯英文短信息解码

  PDU模式的纯英文短信息编码使用GSM字符集的7位编码,此时TP-DCS的值为00。如短信息内容为英文字符“Hi”,首先将各个字符转换为7位的标准二进制ASCII码,然后要将后面字符的低位逐位调整到前面,补齐前面的差别。例如:“H”的二进制ASCII码为1001000,“i” 二进制ASCII码为1101001;显然H的二进制编码不足八位,那么就将后面字符i的最后一位补足到H的前面,就成了11001000(C8),i剩下六位110100,前面再补两个0,变成00110100(34),于是“Hi”就变成了两个八进制数 C834。由于PDU模式的纯英文短信息采用7位编码,解码不方便,因此对于只需发送和接收纯英文字符和数字符号的应用,最好采用Text模式发送和接收短信息。

表2 PDU数据包格式(接收MSM)

备注 名称 长度 数据单元bit位
7 6 5 4 3 2 1 0
  SMSC地址长度 1 N+1(十六进制数)
  SMSC地址类型 1 1 号码类型 号码表
  SMSC号码 N 号码第2位 号码第1位
  号码第4位 号码第3位
  …… ……
  号码第n位 号码第n-1位
  TPDU第一字节 1                
最长12字节 发送源号码长度 1 实际号码位数k(十六进制数)
发送源号码类型 1 1 号码类型 号码表
发送源号码 M 号码第2位 号码第1位
号码第4位 号码第3位
   
号码第k位 号码第k-1位
  TP-PID 1      
  TP-DCS 1          
  TP-SCTS 7 年低位 年高位
  月低位 月高位
  日低位 日高位
  时低位 时高位
  分低位 分高位
  秒低位 秒高位
  时 区
  TP-UDL 1                
最长140字节 TP-UD短信息内容 1                
1                
                 
                 
1                
1                

5.3 中文短信息的解码

  由于中文字的编码是采用2个字节的编码,因此发送和接收中文或中英文混合的短信息只能采用PDU模式。但在GSM标准中,中文编码采用UTF-8的编码,不是目前国内常用的GB-2312编码,故还需要进行中文编码的转换,才能与采用GB-2313汉字库相配合显示汉字字型。

由于UTF-8和GB-2312编码之间不存在一一对应的线性关系,因此只能采用查表的方式进行转换。下面给出一个由UTF-8到GB-2312编码转换的算法。

  ① 建立UTF-8和GB-2312两个中文编码表,表中数据项为2个字节长度的十六进制的数,代表一个中文编码。两个表的长度分别为14 890字节(2×7445)。UTF-8编码表按数据项值从小到大排序,而在GB-2312编码表中,与UTF-8相同位置处为相同汉字的GB-2312码字,如图4所示。

  ② 软件解码过程为:每次从PDU模式SMS数据包的TP-UD中取出两个字节,采用二分法快速数据查找算法,在UTF-8编码表中找到其所在位置,然后在GB-2312表的相同位置处读取相对应的GB-2312编码。解码流程如图5所示。

  ③ 二分法的最坏查找次数为lg2(n+1),UTF-8表的长度n为7445,固最坏查找次数为13次,就是说一个中文编码由UTF-8到GB-2312的转换最多经过13次比较查找就可完成。 这比采用简单的顺序查表要快的多,大大减少了查表所花费的时间,非常适合在一般的嵌入式系统中使用。

  ④ 尽管两个汉字编码表要占用近30 KB(如还需要GB-2312到UTF-8的转换,则还要增加两个表,共占60 KB),但由于采用了ATmega128单片机,其片内有128KB的程序存储器,因此可将程序与表格放在一起。去掉60 KB的表格,仍有近70 KB的容量用于系统程序,因此完全不用外部扩充存储器(汉字字库除外),大大简化了硬件的结构和设计。

结 语

  本文的设计方案已应用在我们研发的产品“车船载GPS-GSM卫星定位无线通信移动终端”上,经过多年的运行和使用,证明系统工作稳定可靠。2001年10月,在美国著名计算机应用杂志《CIRCUIT CELLAR》举办的世界性电子设计竞赛“Design Logic 2001 Contest”中,该产品获得三等奖
 
话题2512093的标题是: gb2312->utf-8或gb5或其他编码,如何? (20分)
分类:数据库-C/S型 xx-xzh (2004-03-20 11:09:00)
不同编码如何实现互相转换?[8D]

低调一贱男 (2004-03-20 11:19:01)
我现在作java,经常接触utf8.呵呵,做了一个.给你,不过好像没有注释

unit main;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, Buttons;

type
TUnicode2GB = class(TForm)
GB: TMemo;
Panel1: TPanel;
SetHeight: TSplitter;
Unicode: TMemo;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
ComboBox1: TComboBox;
Label1: TLabel;
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Unicode2GB: TUnicode2GB;
function AnsiToUnicode(Ansi: string): string;
function Unicode2AscII(s: string): string;
function AnsiToUTF8(Ansi: string): string;

implementation

{$R *.dfm}

procedure TUnicode2GB.BitBtn1Click(Sender: TObject);
begin
Close;
end;

procedure TUnicode2GB.BitBtn2Click(Sender: TObject);
var s: string;
begin
s := GB.Lines.Text;
Unicode.Lines.Clear;

if ComboBox1.Items[ComboBox1.ItemIndex] = 'UTF8' then
Unicode.Lines.append(AnsiToUTF8(s))
else if ComboBox1.Items[ComboBox1.ItemIndex] = 'Unicode' then
Unicode.Lines.append(AnsiToUnicode(s));

Unicode.Lines.append('GB2312码: ' + GB.Lines.Text);
end;

function AnsiToUTF8(Ansi: string): string;
var
s: string;
i: integer;
j, k: string[2];
a: array[1..1000] of char;
begin
s := '';
StringToWideChar(Ansi, @(a[1]), 500);
i := 1;
while ((a <> #0) or (a[i + 1] <> #0)) do begin
j := IntToHex(Integer(a), 2);
k := IntToHex(Integer(a[i + 1]), 2);
s := s + '/u' + k + j;
i := i + 2;
end;
Result := s;
end;

function AnsiToUnicode(Ansi: string): string;
var
s: string;
i: integer;
j, k: string;
a: array[1..1000] of char;
begin
s := '';
StringToWideChar(Ansi, @(a[1]), 500);
i := 1;
while ((a <> #0) or (a[i + 1] <> #0)) do begin
j := inttostr(Integer(a));
k := inttostr(Integer(a[i + 1]));
// showmessage(j+' '+k);
s := s + '/u' + k + j;
i := i + 2;
end;
Result := s;
end;

end.

xx-xzh (2004-03-20 17:43:28)
感谢 低调一贱男!
另:还有 7-bit ASCII串
Binary
UCS2
GB2312
UDHI Indicator
最好能告诉原理,不然总麻烦你也不好,也总不会!

走来走去 (2004-03-20 22:57:27)
C++Builder的例子

==================================
1、 英文编码

缺省的GSM字符集为7位编码,ASCII码为8位编码,编码就是将8位ASCII编码转换为7位编码。

例如:1234 编码后得到31D98C06

2进制表示

8位编码 00110001 00110010 00110011 00110100

7位编码 00110001 11011001 10001100 00000110

通过例子可以看出,将ascii8位编码的Bit8去掉,依次将下7位编码的后几位逐次移到前面,形成新的8位编码。

以下是C++Builder的实现代码:

String __stdcall EncodeEnglish(String InputStr)

{

int n,len,cur;

String tempstr,returnstr;

unsigned char mid1[2],mid2[2];

len=InputStr.Length();

n=0;

for(int i=1;i<=len;i++)

{

if (i<len)

{

strcpy(mid1,InputStr.SubString(i,1).c_str());

strcpy(mid2,InputStr.SubString(i+1,1).c_str());

cur=(mid1[0]>>n)|((mid2[0]<<(7-n))& 0xff);

}

else

{

strcpy(mid1,InputStr.SubString(i,1).c_str());

cur=(mid1[0]>>n)& 0x7f;

}

FmtStr(tempstr,"%2.2X",ARRAYOFCONST((cur)));

returnstr=returnstr+tempstr;

n=(n+1)%7;

if (n==0)

i++;

}

return returnstr;

}

2、 英文解码

简单地说就是将7位字符编码转换为8为字符编码

以下是C++Builder的实现代码:

int ReturnHex(int Value)

{

switch (Value)

{

case 0:

Value=0x7f;

break;

case 1:

Value=0x3f;

break;

case 2:

Value=0x1f;

break;

case 3:

Value=0x0f;

break;

case 4:

Value=0x07;

break;

case 5:

Value=0x03;

break;

case 6:

Value=0x01;

break;

case 7:

Value=0x00;

break;

}

return Value;

}

String __stdcall DecodeEnglish (String InputStr)

{

unsigned char InStr[300];

char OutStr[300];

String str;

int j=0,i=0;

int Point=0;

int temp;

memset(InStr,0,301);

memset(OutStr,0,301);

for(int i=0;i<InputStr.Length();i=i+2)

{

str="0x"+InputStr.SubString(i+1,2);

InStr[i/2]=StrToInt(str);

}

while(j<=InputStr.Length()/2)

{

if(Point==0)

OutStr=InStr[j]&ReturnHex(Point);

else

OutStr=((InStr[j]&ReturnHex(Point))<<Point)|(InStr[j-1]>>(8-Point));

if(Point%7==0&&Point!=0)

Point=0;

else

Point=Point+1;

i++;

j=i-(i/8);


}

OutStr[12]=((InStr[12]&0x07)<<5)|(InStr[11]>>(8-5));

return AnsiString(OutStr);

}

3、 中文编码

中文编码较为简单,就是将GB2312的中文编码转换为代码页为CP936的Unicode编码即可

以下是C++Builder的实现代码

String EncodeChinese(String InputStr)

{

int cur;

String tempstr,returnstr;

WideString ws;

wchar_t mid[2];

ws=WideString(InputStr);

for(int i=1;i<=ws.Length();i++)

{

wcscpy(mid,ws.SubString(i,1).c_bstr());

cur=mid[0];

FmtStr(tempstr,"%4.4X",ARRAYOFCONST((cur)));

returnstr=returnstr+tempstr;

}

return returnstr;

}

4、 中文解码

将代码页为CP936的Unicode编码转换为GB2312的中文编码即可


以下是C++Builder的实现代码

String DecodeChinese(String InputStr)

{

wchar_t Buf[300];

for(int i=0;i<InputStr.Length();i=i+4)

{

Buf[i/4]=StrToInt("0x"+InputStr.SubString(i+1,4));

}

Buf[InputStr.Length()/4]=0;

return WideCharToString(Buf);

}


走来走去 (2004-03-20 22:58:24)
unix 下的c
========================
说明:函数名称
int strUnicode2GB(char *strSourcer, char *strDest,int n)

转换Unicde字符串到GB码,返回汉字数
输入( Unicode 源串,GB2312/ASCII混合编码串,Unicode字节数 必须是偶数!!!)


#include <sys/types.h>

const unsigned short int Unicode_GB2312[][2] =
{

/*Unicode ,GB||ASCII ,MEMO*/
0x0000,0x0040,/* 0 COMMERCIAL AT @ */
0x0001,0x00A3,/* 1 POUND SIGN £ */
0x0002,0x0024,/* 2 DOLLAR SIGN $ */
0x0003,0x00A5,/* 3 YEN SIGN ¥ */
0x0004,0x00E8,/* 4 LATIN SMALL LETTER E WITH GRAVE è */

.............
.............
码表太长了 请尽量通过 Google 查询,多的是
或者通过 stevenkoh@sohu.com 向我索取

0xFF5C,0xA3FC,/* '|' -> 65372 */
0xFF5D,0xA3FD,/* '}' -> 65373 */
0xFF5E,0xA1AB,/* '~' -> 65374 */
0xFFE0,0xA1E9,/* '¢' -> 65504 */
0xFFE1,0xA1EA,/* '£' -> 65505 */
0xFFE3,0xA3FE,/* ' ̄' -> 65507 */
0xFFE5,0xA3A4,/* '¥' -> 65509 */


};

u_int16_t Unicode2GBcode(u_int16_t iUnicode)
{
int i,j,n;

switch (iUnicode){
case 0x0002:
return 0x24;
break;
case 0x000a:
return 0xa;
break;
case 0x000d:
return 0xd;
break;
case 0x0040:
return 0xA1;
break;
}

if ((iUnicode>=0x20&&iUnicode<=0x5a)||(iUnicode>=0x61&&iUnicode<=0x7a)) return iUnicode;


for (i=0,j=0,n=sizeof(Unicode_GB2312)/sizeof(Unicode_GB2312[0])-1;n>0;n>>=1,++j){

if(Unicode_GB2312[0]==iUnicode) return Unicode_GB2312[1];

if (j>1){
if(Unicode_GB2312[i-1][0]==iUnicode) return Unicode_GB2312[i-1][1];
if(Unicode_GB2312[i+1][0]==iUnicode) return Unicode_GB2312[i+1][1];
}

if (Unicode_GB2312[0]<iUnicode) i=i+n;
else i=i-n;
}

if(Unicode_GB2312[0]==iUnicode) return Unicode_GB2312[1];
if(Unicode_GB2312[i-1][0]==iUnicode) return Unicode_GB2312[i-1][1];
if(Unicode_GB2312[i+1][0]==iUnicode) return Unicode_GB2312[i+1][1];

return 0; //转换不成功
}


/*转换Unicde字符串到GB码,返回汉字数*/
int strUnicode2GB(const char *strSourcer,const char *strDest,int n)
{
char cTmp;
u_int16_t hz,tmphz;

char *pSrc;
char *pDest;

int i;


for (i=0,pSrc=strSourcer,pDest=strDest;n>0;n-=2,pSrc+=2,++i,++pDest){

hz=0;
hz=*pSrc<<8|(*(pSrc+1)&0x00FF);
tmphz=Unicode2GBcode(hz);

if (!tmphz||tmphz>0x7F&&tmphz<0xFF){
*pDest='.';
continue;
}
else if (tmphz>0x00&&tmphz<=0x7F){
cTmp=tmphz;
*pDest=cTmp;
}
else{
cTmp=tmphz;
*pDest=(tmphz>>=8);
++pDest;
*pDest=cTmp;
}
}

*pDest='/0';
return i;

}



走来走去 (2004-03-20 22:59:03)
C#.Net 里面实现字符的编码和解码——

#region 生成字符(含英文)引用码
/// <summary>
/// 生成unicode实体引用的wap字符串,所有汉字均由此转换
/// </summary>
/// <param name="s_Chinese">中文字符串,可夹英文</param>
/// <returns></returns>
protected string Gen_Unicode(string s_Chinese)
{
string s_retu="";
char[] c_chars=s_Chinese.ToCharArray();

for(int i=0;i<c_chars.Length;i++)
{
s_retu+="&#x" + ((short)c_chars).ToString("X")+ ";";
}

return s_retu;
}
/// <summary>
/// 把 WAP 代码转换为字符(中文字符串,可夹英文)
/// </summary>
protected string Gen_Chinese(string s_Unicode)
{
string s_retu="";
string s1="";
string s2="";
byte[] array = new byte[2];
char []spar={';'};
string []chinese = s_Unicode.Split(spar);
int count=chinese.Length;
if(count>0)
{
for(int i=0;i<count;i++)
{
string s_tmp=chinese.Trim();
if(s_tmp!="")
{
// s_tmp=s_tmp.Substring(4);
if(s_tmp.Length>=4)
{
s1 = s_tmp.Substring(0,2);
s2 = s_tmp.Substring(2,2);
array[0] = (byte)Convert.ToInt32(s1,16);
array[1] = (byte)Convert.ToInt32(s2,16);
s_retu =s_retu + System.Text.Encoding.BigEndianUnicode.GetString(array);
}
else //英文的
{
// s1 = s_tmp.Substring(0,2);
s1 = "00";
s2 = s_tmp;
array[0] = (byte)Convert.ToInt32(s1,16);
array[1] = (byte)Convert.ToInt32(s2,16);
s_retu =s_retu + System.Text.Encoding.BigEndianUnicode.GetString(array);
}
}

}

}
return s_retu;
}
/// <summary>
/// 把字符转换为双字节的 hex
/// </summary>
/// <param name="s_Chinese">中文字符串,可夹英文</param>
protected string Gen_Hex(string s_Chinese)
{
string s_retu="";
char[] c_chars=s_Chinese.ToCharArray();

for(int i=0;i<c_chars.Length;i++)
{
string hex=((short)c_chars).ToString("X");
if(hex.Length==2)//如果是单字节的则转换为双字节的字符
hex = "00" + hex;
s_retu+=hex;
}

return s_retu;
}
/// <summary>
/// 把 hex 代码转换为字符(中文字符串,可夹英文)
/// </summary>
protected string Gen_CharFromCode(string code)
{
string s = "";
for(int i=0;i<code.Length;i+=4)
{
string s1 = code.Substring(i,2);
string s2 = code.Substring(i+2,2);

int t1 = Convert.ToInt32(s1,16);
int t2 = Convert.ToInt32(s2,16);
byte[] array = new byte[2];

array[0] = (byte)t1;
array[1] = (byte)t2;

s += System.Text.Encoding.BigEndianUnicode.GetString(array);
}
return s;
}

#endregion



走来走去 (2004-03-20 22:59:29)
c++的编码、解码

#include <string.h>
#include <stdio.h>

#define BYTE unsigned char

void code( BYTE *p, int len, BYTE *q )
{
int i,j;
for( i=j=0; i<len; i++ )
{
if( i%8 == 7 )
continue;
char next = (i<len)?p[i+1]:0;
q[j++] = (p>>i%8) + ((next&((1<<(i%8+1))-1))<<8-i%8-1);
}
q[j]=0;
}

void dcode( BYTE *p, int len, BYTE *q )
{
int i, j;
BYTE temp = 0;
for(i=j=0;i<len;i++)
{
q[j++] = ((p&((1<<8-i%7-1)-1))<<i%7)+temp;
temp=p>>(8-i%7-1);
if( i%7 == 6 )
{
q[j++] = temp;
temp = 0;
}
}
q[j] = 0;
}

void main()
{
char p[] = "234312l;asdkfpqwrjasdfjqwjrlashfnoqwerhkasdfqwerqwerqwerqwer";
char q[256];
char r[256];

code( (BYTE *)p, strlen(p), (BYTE *)q );
dcode( (BYTE *)q, strlen(q), (BYTE *)r );

printf( "%s/n", r );
}



走来走去 (2004-03-20 23:00:24)
delphi解码
=================
function UnicodeToString(var AString: string; AUnicode: PChar; ALenth: integer): integer;
{**********************************
功能:网络unicode转gb
AString,输出字符串
AUnicode:输入数组,接收到的直接传进来,不用高低互换了
ALenth:长度
***********************************}
var
TmpBuf: array [1..1024] of char;
TmpChar: char;
TmpLen, i: integer;
begin
try
TmpLen := ALenth div 2;
if ALenth > 0 then
begin
CopyMemory(@TmpBuf, AUnicode, ALenth);
for i := 0 to TmpLen - 1 do
begin
TmpChar := (AUnicode + i * 2)^;
(AUnicode + i * 2)^ := (AUnicode + i * 2 + 1)^;
(AUnicode + i * 2 + 1)^ := TmpChar;
end;
TmpBuf[TmpLen * 2 + 1] := #0;
TmpBuf[TmpLen * 2 + 2] := #0;
AString := WideCharToString(pwidechar(AUnicode));
Result := TmpLen;
end
else
begin
Result := 0;
end;
except
AString := '';
Result := 0;
end;
end;


走来走去 (2004-03-20 23:01:00)
java解码

==============
/*
* UnicodeTest.java
*
* Created on July 29, 2003, 12:59 PM
*/

/**
*
* @author abc
* @version
*/

public class UnicodeTest
{

public static void main(String args[])
{
UnicodeTest UT = new UnicodeTest();
UT.test1();
}

public void test1()
{
String str = "测试信息abc123";
try
{
byte[] b = str.getBytes("GBK");
System.out.println(str + " -(GBK)编码: " + bytesToHexStr(b));
System.out.println("");

str = new String(b, "GBK");
System.out.println("从GBK编码 " + bytesToHexStr(b) + " 重新转换为字串: " + str);
System.out.println("");

b = str.getBytes("UnicodeBigUnmarked");
System.out.println(str + " -(UCS2)编码: " + bytesToHexStr(b));
System.out.println("");

str = new String(b, "UnicodeBigUnmarked");
System.out.println("从(UCS2)编码 " + bytesToHexStr(b) + " 重新转换为字串: " + str);
System.out.println("");

b = str.getBytes("ASCII");
System.out.println(str + " -(ASCII)编码: " + bytesToHexStr(b));
System.out.println("");
}
catch(Exception e){}
}

private String bytesToHexStr(byte[] b)
{
if (b == null) return "";
StringBuffer strBuffer = new StringBuffer(b.length * 3);
for(int i = 0; i < b.length; i++)
{
strBuffer.append(Integer.toHexString(b & 0xff));
strBuffer.append(" ");
}
return strBuffer.toString();
}

}

运行此小程序的输出结果是:


测试信息abc123 -(GBK)编码: b2 e2 ca d4 d0 c5 cf a2 61 62 63 31 32 33

从GBK编码 b2 e2 ca d4 d0 c5 cf a2 61 62 63 31 32 33 重新转换为字串: 测试信息abc123

测试信息abc123 -(UCS2)编码: 6d 4b 8b d5 4f e1 60 6f 0 61 0 62 0 63 0 31 0 32 0 33

从(UCS2)编码 6d 4b 8b d5 4f e1 60 6f 0 61 0 62 0 63 0 31 0 32 0 33 重新转换为字串: 测试信息abc123

测试信息abc123 -(ASCII)编码: 3f 3f 3f 3f 61 62 63 31 32 33
 
如果你要处理包含汉字等多字节字符的字符串的话,用AnsiString数据类型和带Ansi前缀的字符串处理函数(比如AnsiPos)就好了,没有必要用UTF-8或WideString等Unicode字符串数据类型的。
 

Similar threads

回复
0
查看
873
不得闲
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
628
import
I
后退
顶部