祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 15762|回复: 9

[其它] 关于PowerBuilder中的字符集问题

[复制链接]

[其它] 关于PowerBuilder中的字符集问题

[复制链接]
dazizai

主题

0

回帖

652

积分

版主

积分
652
贡献
在线时间
小时
2020-12-3 14:48:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
关于PowerBuilder中的字符集问题

搞PB的人,很多对字符集编码这个东西不理解。即使看了网上的文章,还是不懂。比如https://blog.csdn.net/qq_28098067/article/details/53486032这篇文章,就是非常好的一篇介绍字符集的文章。大家可以先耐心看一下这篇文章。
本文不研究高深的字符集问题,仅仅就PowerBuilder里字符集使用问题,作一个简介。
在PB里的字符串处理,我们熟悉的就是 string。这个string 类型,对于不同版本,是有区别的,PB9.0及以下版本,它使用的是GB2312编码(也就是ASC码编码方案),对PB10及以上版本,它使用的是UNICODE 版本。对于存储字符串来说,这两者完全不兼容,需要做转换。

一、不同字符集的内存存储形态
下面举一个例子说明:
String ls_str = “国3a”
对于这个字符串,它在PB9及以下的内存里存储是这样的(十六进制形式):
表一:
  B9
  
  FA
  
  33
  
  61
  
  \0
  
   
  
对于这个字符串,它在PB10及以上的内存里存储是这样的(十六进制形式):
表二:
  B9
  
  \0
  
  FA
  
  \0
  
  33
  
  \0
  
  61
  
  \0
  
  \0
  
  \0
  
   
  
   
  
(注意:\0表示asc码的0,即NULL)
我们看内存里,它的区别很显然:
1.  PB9里占用的内存只是PB10里占用的内存一半。
2.  PB9里以一个字节为一个长度,所以这个len(ls_str)结果为4,而PB10里len(ls_str)结果为3。而PB10里又增一个函数lenA(ls_str)它是按照PB9的方式来取,结果为4。
以上是内存里的保存形态,实际使用UNICODE时那么多\0不需要你处理,系统会自动处理好,给你放到 string 里面取用。

二、不同字符集的互相转换
那么 ,为什么PB9.0 -> PB10.0这样升级,改字符集呢?原因有:
1.      gb2312显示的字符个数比较少,不能显示冷僻字,尤其对东亚一些宽字节文字无法处理。
2.      用mid函数,无法取到整体汉字,在PB9里mid(ls_str,1,1)只能取到半个汉字,PB10里面mid(ls_str,1,1)就能取到“国”,如果要和PB9里一样取半个汉字,它也增加了一个函数,用midA(ls_str,1,1)。
以上是介绍了PB9和PB10不同的字符集问题,那么PB9里是否可以使用UNICODE,PB10里是否可以使用gb2312呢?答案是肯定可以的。不要忘了,我们还有个类型叫做blob,这个类型很简单,它不负责字符转换,只是保存内存里二进制原有形态。
Blob blb_data
PB9里blb_data = blob(ls_str),这时候blb_data里的形态就是
表三:
  B9
  
  FA
  
  33
  
  61
  
  \0
  
   
  

而在PB10里面blb_data =blob(ls_str),这时候blb_data里的形态就是

表四:
  B9
  
  \0
  
  FA
  
  \0
  
  33
  
  \0
  
  61
  
  \0
  
  \0
  
  \0
  
   
  
   
  

而在PB10里面blb_data =blob(ls_str, EncodingANSI!),这时候blb_data里的形态就是

表五:
  B9
  
  FA
  
  33
  
  61
  
  \0
  
   
  
这时候与PB9的表一表三是一样的。

PB10里表二表四这样的数据转换成PB10的字符串,很简单:ls_str = string(blb_data)
PB10里表一表三这样的数据转换成PB10的字符串:
ls_str = string(blb_data,EncodingANSI!)
而在PB9里,要将 gb2312转成 UNICODE,要稍微麻烦点,得借助WINAPI函数MultiByteToWideChar。这个比较复杂一点,此处不缀述,解决方案,本文最后会给出。

三、UTF8字符集问题
UNICODE已经很好地解决了多种语言字符集在计算机上的显示和存储问题,但是,在这个网络时代,我们还要考虑到网络传输问题。
对比表一和表二,我们看出,表二占用的内存比表一多一倍,同理,传输也要多花费一倍的网络流量。这很不划算。UTF8就由此诞生。下表就是“国3a”在内存里的形态:
表六:
  E5
  
  9A
  
  BD
  
  33
  
  61
  
  \0
  
   
  
   
  
   
  
   
  
   
  
   
  
从表六可以看出,作为单字节的“3a”存储与PB9里的gb2312是一样的,而“国”由存为3个字节。总数上比UNICODE少了6个字节。
UTF8字符集既解决了多语言宽字节字符集存储问题,也提高了网络传输的效费比。所以,网络传输中几乎都默认使用UTF8字符集传输。

四、windows操作系统对字符集的处理
在我们日常使用的windows操作系统中,它提供了一整套WINAPI用于处理字符串,遗憾的是它无法直接显示UTF8字符集,必须转换成gb2312或UNICODE才能正确显示。
对于gb2312和UNICODE编码,windows为我们提供了2套WINAPI函数。通常以A和W结尾。
例如:

在PB9里我们这样声明函数,注意 alias for “…..A”和alias for “…..W”里的不同:

FUNCTION ulong PlaySound(string lpszName,ulong hModule,ulongdwFlags) LIBRARY "winmm.dll" ALIAS FOR "PlaySoundA"

在PB10里我们这样声明函数:

FUNCTION ulong PlaySound(string lpszName,ulong hModule,ulongdwFlags) LIBRARY "winmm.dll" ALIAS FOR "PlaySoundW"

实际上在winmm.dll这个函数中,widnows分别为我们提供了PlaySoundA和PlaySoundW这两个函数,分别用于处理不同字符集编码下的同一个功能,
这两种声明,PB会直接把自己的字符集变量传给WINAPI处理。
此处需要注意,在PB10以上版本中使用WINAPI,请不要使用声明带A的函数,而应使用带W的函数。
对于自己的一些DLL实现的功能,没有windows操作系统那么尽责尽力,往往只有char *这样的参数形式,这类函数声明,使用PB9的方式即可:

FUNCTION ulong MyFunc(string szName) LIBRARY "my.dll" aliasfor “MyFunc”

在PB10以上版本中要使用此DLL,需要声明为:

FUNCTION ulong MyFunc(string szName) LIBRARY "my.dll"alias for “MyFunc;ansi”

注意后面多了一个 “;ansi”,PB会自动在内部进行字符集转换。这种转换不是百分之百成功有用,遇过多次这种方式是有问题的。随着PB9以下版本的应用升级到PB10以上,相应的DLL最好也能把字符集编码升级成UNICODE,就象windows的WINAPI那样,搞2套函数实现。

五、关于PB开发中字符集转换的方案
实际开发中,我们经常遇到字符集转换问题,同样的代码,在PB9和PB10版本中,不能通用,很多应用由PB9升级后,虽然业务逻辑没问题,但自定义的加密解密算法、编码解码算法、老版本的DLL使用问题,都会导致升级失败,没有统一的字符集处理接口。
在我写的PB_Json_httpclient_crypto_ftp 这个库里(简称pbjson库),我对PB9和PB10的字符集转换做了统一接口。尤其是在处理UTF8的时候,2个函数ToUtf8 和 FromUtf8分别完成从string转到UTF8和从UTF8转成string,让你不用关心当前使用的是 gb2312 还是 unicode字符集,全部自动转换完成 ,确保pb9和pb10代码一致性。

同时pbjson库里还有大量工具对字符集进行了自动转换,例如httpclient涉及到的WEB应用,uo_json涉及到接口应用等。








大自在(QQ:781770213)
2020、12、3

评分

参与人数 1威望 +30 收起 理由
ehxz + 30 很给力!

查看全部评分

共享共进共赢Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
xiaoguang328

主题

0

回帖

361

积分

中级会员

积分
361
贡献
在线时间
小时
2020-12-3 16:15:11 | 显示全部楼层
膜拜大神
共享共进共赢Sharing And Win-win Results
flyingdancex

主题

0

回帖

8959

积分

论坛元老

积分
8959
贡献
在线时间
小时
2020-12-4 20:31:47 | 显示全部楼层
留个脚印吧....
共享共进共赢Sharing And Win-win Results
wfliu

主题

0

回帖

664

积分

高级会员

积分
664
贡献
在线时间
小时
2020-12-13 14:08:47 | 显示全部楼层
学习了 ,要不还真没注意到,
共享共进共赢Sharing And Win-win Results
songzhenyi

主题

0

回帖

321

积分

中级会员

积分
321
贡献
在线时间
小时
2021-1-17 18:36:44 | 显示全部楼层
学习了,一直没有搞清楚
共享共进共赢Sharing And Win-win Results
udun

主题

0

回帖

19

积分

新手上路

积分
19
贡献
在线时间
小时
2021-9-2 13:38:01 | 显示全部楼层
多谢,好好学习一下
共享共进共赢Sharing And Win-win Results
xister

主题

0

回帖

511

积分

高级会员

积分
511
贡献
在线时间
小时
2021-11-9 11:13:20 | 显示全部楼层
一年前的文章了,依然值得学习!
共享共进共赢Sharing And Win-win Results
hanxuqi

主题

0

回帖

666

积分

高级会员

积分
666
贡献
在线时间
小时
2021-11-12 15:52:53 | 显示全部楼层
写的非常详细
共享共进共赢Sharing And Win-win Results
hanxuqi

主题

0

回帖

666

积分

高级会员

积分
666
贡献
在线时间
小时
2021-11-15 09:42:51 | 显示全部楼层
说的太详细了
共享共进共赢Sharing And Win-win Results
lifei1210

主题

0

回帖

478

积分

中级会员

积分
478
贡献
在线时间
小时
2022-1-15 21:05:27 | 显示全部楼层
学习了 ,以后会注意
共享共进共赢Sharing And Win-win Results
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2024-4-26 12:15 , Processed in 0.055974 second(s), 11 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表