ehxz 发表于 2015-2-11 12:38:29

PB中字符编码转换[ansi, UTF8, Unicode] API: WideCharToMultiByte() MultiByteToW...

PB中字符编码转换 API: WideCharToMultiByte()MultiByteToWideChar ()函数运用
    由于项目的需要和服务器进行XML格式的报文交互。可是服务器返回的报文是UTF8格式的,PB开发工具目前的只支持ANSI编码格式。经过多方的查找资料以及不断的实验调试,终于完成了。

    字符编码格式在这里就不做详细的叙述,大家可以自己到网上去参考相关文档。

=========================================API 参考===============================================
    利用windows系统自带的API函数进行转换,附带函数参数说明,如果还需要更详细的资料可以网上搜索:
      int MultiByteToWideChar(UINT CodePage,DWORD dwFlags, LPCSTR lpMultiByteStr,int cchMultiByte, LPWSTR lpWideCharStr,int cchWideChar );
CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值。[说白了就unicode需要转换成什么字符编码]: (我想最常用的应该是CP_ACP(0)和CP_UTF8(65001) )
dwFlags: 指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。
lpMultiByteStr:指向将被转换字符串的字符。
cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个数。如果lpMultiByteStr指定的字符串以空字符终止,可以设置为-1(如果字符串不是以空字符中止,设置为-1可能失败,可能成功),此参数设置为0函数将失败。
lpWideCharStr:指向接收被转换字符串的缓冲区。
cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字符个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。
返回值:
如果函数运行成功,并且cchWideChar不为零,返回值是由lpWideCharStr指向的缓冲区中写入的宽字符数;
如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所需求的宽字符数大小。
如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
它可以返回下面所列错误代码:ERROR_INSUFFICIENT_BUFFER;ERROR_INVALID_FLAGS;ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。


int WideCharToMultiByte(UINT CodePage,DWORD dwFlags,LPWSTR lpWideCharStr,int cchWideChar,LPCSTR lpMultiByteStr,int cchMultiByte,LPCSTR lpDefaultChar,PBOOL pfUsedDefaultChar);
CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值[说白了就是什么字符编码转换成unicode编码。常用CP_ACP(0)和CP_UTF8(65001)
dwFlags: 指定如何处理没有转换的字符,但不设此参数函数会运行的更快一些,我都是把它设为0。
lpWideCharStr: 待转换的宽字符串。
cchWideChar: 待转换宽字符串的长度,-1表示转换到字符串结尾。
lpMultiByteStr: 接收转换后输出新串的缓冲区。
cbMultiByte: 输出缓冲区大小,如果为0,lpMultiByteStr将被忽略,函数将返回所需缓冲区大小而不使用lpMultiByteStr。
lpDefaultChar: 指向字符的指针, 在指定编码里找不到相应字符时使用此字符作为默认字符代替。如果为NULL则使用系统默认字符。
                            对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。
lpUsedDefaultChar:开关变量的指针,用以表明是否使用过默认字符。对于要求此参数为NULL的dwFlags而使用此参数,函数将失败返回并设置错误码ERROR_INVALID_PARAMETER。
                                    lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些。
返回值:
如果函数成功,且cbMultiByte非0,返回写入lpMultiByteStr的字节数(包括字符串结尾的null);cbMultiByte为0,则返回转换所需 字节数。函数失败,返回0。
若想获得更多错误信息,请调用GetLastError函数。它可以返回下面所列错误代码: ERROR_INSUFFICIENT_BJFFER;ERROR_INVALID_FLAGS; ERROR_INVALID_PARAMETER;ERROR_NO_UNICODE_TRANSLATION。
注意:指针lpMultiByteStr和lpWideCharStr必须不一样。如果一样,函数将失败,GetLastError将返回ERROR_INVALID_PARAMETER的值。
========================================================================================
从上面的API可以看出,系统只有从unicode到多字节字符之间的转换,没有多字节与多字节自己之间的转换,所以我们一般通过转换为unicode格式作为一个中介,然后再转换成自己需要的字符编码格式。
PB中的函数声明:
    FUNCTION long WideCharToMultiByte(uint CodePage, ulong dwFlags, ref blob lpWideCharStr, long cchWideChar, ref blob lpMultiByteStr, long cbMultiByte, long lpDefaultChar,long lpUsedDefaultChar) Library "kernel32.dll"

FUNCTION long MultiByteToWideChar(uint CodePage, ulong dwFlags, ref blob lpMultiByteStr,long cchMultiByte,ref blob lpWideCharStr,long cchWideChar) LIBRARY "kernel32.dll"

注意:

[*]在WideCharToMultiByte 函数中cchWideChar这个参数表示多少个unicode字符需要转换,其它语言我不知道在PB中统计出来需要转换的大写是字节数,因为unicode是2个自己的,所以需要除以2得出unicode字符数,同样的道理 MultiByteToWideChar 函数中cchMultiByte 是要乘以2的字节控件才能容纳转换后unicode。 刚开始不明白一直转换出来是乱码,原因就在这里,真是坑爹的参数。可能是PB没有宽字符的概念吧,统一都用字节做单位。
[*]MultiByteToWideChar 中lpWideCharStr, cchWideChar 两个参数,看参考文档是要设置为NULL值,但是在PB里面调用的话一定要变成0,要是也是null执行,函数就返回0,报参数错误。。。原因未知。。
[*]还有就是常识: PB long型才是对应系统API的integer整型,所以声明的时候要注意了。
总得说来,要是明白了字符编码的各个关系,调用函数还是很简单的,以前觉得很晕乎的东西,现在突然间豁然开朗了,对于问题的解决还是要多动手多试验,光看资料是解决不了问题的。
好了废话不多说啦 ,直接上代码,代码才是硬道理。。。O(∩_∩)O~

//*******************************************code***********************************************************
//代码在PB9,window7 64bit 测试通过,对代码有疑问的可以发送邮件进行咨询xiedaolin2000@163.com
//-----------------------------------------of_unicode_utf8-----------------------------------------------------------------
// 函数: n_cst_utilities::of_unicode_utf8()
//--------------------------------------------------------------------
// 描述: Unicode编码转换为UTF8编码
//--------------------------------------------------------------------
// 参数:
// reference blob ablb_unicode
// reference blob ablb_UTF8   
//--------------------------------------------------------------------
// 返回值:long 转换后的字节数
//--------------------------------------------------------------------
// 作者: xiedaolin 日期: 2012.12.13
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================
long ll_Unicode_Size, ll_UTF8_Size


ll_Unicode_Size = len(ablb_unicode)
if ll_Unicode_Size < 1 then
return 0
end if
ll_Unicode_Size = ll_Unicode_Size/2
//获取转换需要的字节数
ll_UTF8_Size = WideCharToMultiByte(CP_UTF8, 0, ablb_unicode, ll_Unicode_Size, ablb_utf8, 0, 0, 0)
if ll_UTF8_Size < 1 then
return 0
end if


ablb_utf8 = Blob(space(ll_UTF8_Size))
ll_UTF8_Size = WideCharToMultiByte(CP_UTF8, 0, ablb_unicode, ll_Unicode_Size, ablb_utf8, ll_UTF8_Size, 0, 0)
if ll_UTF8_Size < 1 then
return 0
end if
return ll_UTF8_Size

//------------------------------------------------of_utf8_unicode----------------------------------------------------------
//====================================================================
// 函数: n_cst_utilities::of_utf8_unicode()
//--------------------------------------------------------------------
// 描述: UTF-8 编码转换为 Unicode 编码格式
//--------------------------------------------------------------------
// 参数:
// reference blob ablb_UTF8   
// reference blob ablb_Unicode
//--------------------------------------------------------------------
// 返回值:integer 多少字节被转换
//--------------------------------------------------------------------
// 作者: xiedaolin 日期: 2012.12.13
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================


long ll_UTF8_Size
long ll_Unicode_Byte_Size, ll_Unicode_WChar_Size
blob lblb_null


setnull(lblb_null)




ll_UTF8_Size = len(ablb_UTF8)


//获取转换后需要的内存空间
ll_Unicode_WChar_Size = MultiByteToWideChar(CP_UTF8, 0, ablb_UTF8, ll_UTF8_Size, lblb_null, 0)
if ll_Unicode_WChar_Size < 1 then
return 0
end if


ll_Unicode_Byte_Size = ll_Unicode_WChar_Size * 2
ablb_Unicode = blob(space(ll_Unicode_Byte_Size))


//开始转换
ll_Unicode_WChar_Size = MultiByteToWideChar(CP_UTF8, 0, ablb_UTF8, ll_UTF8_Size, ablb_Unicode, ll_Unicode_Byte_Size)
if ll_Unicode_WChar_Size < 1 then
return 0
end if


return ll_Unicode_Byte_Size

//-----------------------------------------------of_ANSI_Unicode-----------------------------------------------------------
//====================================================================
// 函数: n_cst_utilities::of_ANSI_Unicode()
//--------------------------------------------------------------------
// 描述: ANSI 编码转换为 Unicode 编码格式
//--------------------------------------------------------------------
// 参数:
// value   string as_ANSI      
// reference blob   rblb_Unicode
//--------------------------------------------------------------------
// 返回值:long 多少字节被转换
//--------------------------------------------------------------------
// 作者: xiedaolin 日期: 2012.12.13
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================


long ll_ANSI_Size
long ll_Unicode_Byte_Size, ll_Unicode_WChar_Size
blob lblb_ANSI
blob lblb_null


setnull(lblb_null)


lblb_ANSI = BLOB(as_ansi)
ll_ANSI_Size = len(lblb_ANSI)


//获取转换后需要的内存空间
ll_Unicode_WChar_Size = MultiByteToWideChar(CP_ACP, 0, lblb_ANSI, ll_ANSI_Size, lblb_null, 0)
if ll_Unicode_WChar_Size < 1 then
return 0
end if


ll_Unicode_Byte_Size = ll_Unicode_WChar_Size * 2
rblb_unicode = blob(space(ll_Unicode_Byte_Size))


//开始转换
ll_Unicode_WChar_Size = MultiByteToWideChar(CP_ACP, 0, lblb_ANSI, ll_ANSI_Size, rblb_unicode, ll_Unicode_Byte_Size)
if ll_Unicode_WChar_Size < 1 then
return 0
end if


return ll_Unicode_Byte_Size

//---------------------------------------------------of_ANSI_UTF8-------------------------------------------------------
//====================================================================
// 函数: n_cst_utilities::of_ANSI_UTF8()
//--------------------------------------------------------------------
// 描述: ANSI 编码 转换为 UTF8 编码
//--------------------------------------------------------------------
// 参数:
// reference string as_ANSI   
// reference blob   ablb_UTF8
//--------------------------------------------------------------------
// 返回值:long 转换后的字节数
//--------------------------------------------------------------------
// 作者: xiedaolin 日期: 2012.12.13
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================


blob lblb_Unicode
long ll_Unicode_Size, ll_UTF8_Size


if isnull(as_ansi) or len(as_ansi) = 0 then
return 0
end if


lblb_Unicode   = ToUnicode(as_ansi)
ll_Unicode_Size = len(lblb_Unicode)


of_ANSI_Unicode(as_ansi, lblb_Unicode)
ll_Unicode_Size = len(lblb_Unicode)


if ll_Unicode_Size < 1 then
return 0
end if
ll_UTF8_Size = of_unicode_utf8( lblb_Unicode, ablb_utf8)
return ll_UTF8_Size

//------------------------------------------------of_UTF8_ANSI----------------------------------------------------------
//====================================================================
// 函数: n_cst_utilities::of_UTF8_ANSI()
//--------------------------------------------------------------------
// 描述:
//--------------------------------------------------------------------
// 参数:
// reference blob   ablb_UTF8
// reference string as_ANSI   
//--------------------------------------------------------------------
// 返回值:integer
//--------------------------------------------------------------------
// 作者: xiedaolin 日期: 2012.12.13
//--------------------------------------------------------------------
// 修改历史:
//
//====================================================================


blob lblb_Unicode, lblb_ANSI
long ll_Unicode_Size, ll_UTF8_Size


ll_Unicode_Size = of_UTF8_Unicode(ablb_utf8, lblb_Unicode)
if ll_Unicode_Size < 1 then
return 0
end if
as_ansi = FromUnicode(lblb_Unicode)
return len(as_ansi)

//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------



from:http://xiedaolin2000.blog.163.co ... 563201211147444823/
如有问题,请联系。

johnxiangchina 发表于 2015-2-13 17:22:04

支持一下。前段时间也遇到了这个问题。忘记怎么解决的了

yuhaihao1234 发表于 2015-8-27 16:58:17

如何设置会使pb中栏位包含中英文时换行不会错乱

fuxiaoyang13 发表于 2015-8-30 19:20:08

多谢分享!!!!!

swimchen 发表于 2015-9-3 00:03:48

不错,印象中,我记得在PB9,你还可以用ToAnsi和ToUnicode来处理,然后用String(UTF),我不知道怎么回事,PB9的帮助有提到过可以和PB11.5或以上版本的直接转换,但是怎么测试都不行,网上我记得有个DLL可以直接转换STRING和FILE的!效果也不错

mozhen01 发表于 2021-12-25 16:52:54

非常好的用例。
页: [1]
查看完整版本: PB中字符编码转换[ansi, UTF8, Unicode] API: WideCharToMultiByte() MultiByteToW...

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

Mail To:Admin@SybaseBbs.com