转载自: http://hi.baidu.com/heroofhero/blog/item/049d8c1e5843c9c1a6866903.html

1.HessianPHP的DateTime问题
我在家使用时发现了问题,php上显示错误“Cannot redeclare class DateTime”。经调查发现,从PHP5.2开始php有了叫DateTime的类型,见文章http://laughingmeme.org /2007/02/27/looking-at-php5s-datetime-and-datetimezone/,这就与HessianPHP包定义 的DateTime类冲突,所以导致了上面的错误。我在公司用的是php 5.0.x的版本没问题,在家用了php5.2.x的版本就有问题。
这就有问题,现在很多客户已使用了PHP的新版本,直接用就不行了,而HessianPHP也没有更新。所以目前只能自己解决。解决方法是:将 HessianPHP包中使用的DateTime的地方改成别的名字,如HessianDateTime,经我测试没问题了。
这个问题在其开源项目已有人提到,见http://sourceforge.net/tracker/index.php?func=detail& amp;aid=1804163&group_id=126933&atid=707220,问题解决了,基本做法也是将两个文件里的名 字改了。

2. HessianPHP的中文字符编码问题
Hessian调用的中文问题,Java之间调用没有乱码问题,与其它主要语言(C#,Python)应该也是没问题的(未测试),但与PHP直接传输中 文字符串就有问题,双向都有问题。经研究,HessianPHP的实现有问题。另外,PHP本身对处理中文字符串有问题,PHP没有很好的支持 Unicode,PHP中的字符串是按字节处理的 。
目前解决方法,需要在php客户端和java服务端都做urlencode和urldecode编解码。因为编码后的传输只有ascii字符了,而ascii字符传输没问题。这样就解决了中文问题。
但这种方法有几个缺点:

  1. 需要客户端和服务端双方都要对中文做编解码。
  2. 服务端是向所有客户提供服务的,不只是php客户端。采用此方法后将使以后其它客户端访问此服务也需要编解码。

我对HessianPHP处理中文字符串错误,研究结果如下:
在HessianPHP包中,负责发送String是要用到HessianWriter类writeStringData方法,此类定义在Protocal.php文件中:
function writeStringData($value){
$this->stream .= pack('n',strlen($value));
$this->stream .= utf8_encode($value);
}
在Hessian协议中字符串是要以utf8编码方式传输的,所以这里原作者用了utf8_encode函数。但问题是utf8_encode是将 ISO-8859-1 编码的字符串转换为 UTF-8 编码,问题就是这里。如果我们用的php源文件本身就是utf8编码的,那么其中的中文字符串已经是utf8编码了(php只把字符串看作字节),再用 utf8_encode函数就等于把已经是utf8的内容又做了一次编码,所以收到的内容当然是乱码了。我在这里把utf8_encode函数去掉,直接 用$value,收到的就不是乱码。如我发送“韩国恺”,收到的内容是“韩国恺z”,可以看出问题就在这里。但又有问题了,“韩国恺”的后面多个一个 “z”,说明别的地方自然就少了一个“z”,“z”其实表示一个终结符,服务器端报错 “com.caucho.hessian.io.HessianProtocolException: hello: expected end of call ('z') at end of stream.”。推测可知,这个问题是前面计算字符串长度strlen($value)有误导致的问题,根据Hessian字符串映射的定义, 长度是按照16bit字符长度计算的,并不一定等于字节的数量strlen($value)。也就是说,长度应该是Unicode的字符数。而PHP中的 strlen函数其实只是得到了字符串的字节数,不是真正的字符数,中文是多字节的,当然有问题。清楚原因了,我们可以解决这个问题。很简单,将 strlen函数替换为我后面定义的utf8_strlen函数即可,utf8_strlen函数返回的是这个utf8编码的字符串的真正字符数,作用如同Java中String的length方法一样。最后,经我修改后,终于解决了php发送中文的乱码问题。修改后的代码如下:
function writeStringData($value){
$this->stream .= pack('n',utf8_strlen($value));
$this->stream .= $value;
}
另外,HessianPHP中,负责解析字符串的HessianParser类的readString方法也有问题,导致php收到的中文字符串也有问 题,变成了问号。有经验的人很清楚,一般将UTF-8/GBK等多字节编码转换为ASCII/ISO-8859-1的单字节编码时,不兼容的部分就会变成 问号了。通过查看Protocal.php文件HessianParser类的readString方法,可以看出作者已经考虑根据UTF-8读取字节的 问题,但是该方法的最后一句话“return utf8_decode($string);”就出了问题。utf8_decode函数是把字符串转成ISO-8859-1的编码,那当然中文就成了问 号!最后,只要改为“return $string;”就可以了。
终于,修改后的Hessian的PHP实现可以按照Hessian协议标准正常的收发中文字符串了!这是完全透明的。
这种方法才是从根本上解决了Hessian PHP的问题,完全没有前面解决方法的所有缺点。有点麻烦的是,要自己修改源文件的几个地方。我会向作者反映这个问题,希望以后版本能够改进,继续支持开源。

以上可以看出,HessianPHP的实现者在国际化(I18N)方面的理解上不够,没有正确理解php中utf8_encode和 utf8_decode函数。还可以看出PHP不支持Unicode真的很烂,比起其它Java等支持Unicode的语言要多走一些弯路。
实际上,PHP与Java的xml-rpc调用上也存在类似的问题,这可不是Java的问题。

我认为Hessian的PHP支持不好。下载的最新HessianPHP包中,显示有“HessianPHP 1.0.5 RC2 (PHP4 & 5) Release Date: 2005-12-29”,从06年开始就没有更新过了,只有少数人在维护,且支持处于不活跃状态。另外,文档不够详细,细节需要看源文件。如果遇到什么问 题,只能我们自己解决了,这是一种额外的负担。

提示:
除了使用Hessian作为rpc协议外,使用基本的RESTful的方式也可以很轻松的实现服务,比如通过http get或post方法把参数传过来,返回特定的xml或json格式的结果。这种方式非常简单、灵活,且语言、平台无关,不需要额外对中文编解码。

function utf8_strlen($str)
{
$count = 0;

for($i = 0; $i
< strlen($str); $i++)
{
$value = ord($str[$i]);

if($value > 127)
{
if($value >= 192 &&
$value <= 223)
$i++;
elseif($value >= 224
&& $value <= 239)
$i = $i + 2;

elseif($value >= 240 && $value <= 247)
$i = $i +
3;
else
die('Not a UTF-8 compatible
string');
}

$count++;
}

return $count;
}

转载于:https://www.cnblogs.com/DavidYan/articles/2133954.html

[转]HessianPHP 中文支持,中文乱码问题解决相关推荐

  1. oracle 菱形乱码,Ubuntu Server 16.04中文方块菱形乱码问题解决

    Ubuntu Server 16.04中文方块菱形乱码问题解决 这里只讲tty的中文方块乱码 默认的tty只能显示一个字节128或256字符,你可以用setfont命令去改tty的字体,但是永远只能局 ...

  2. java.net.url 中文乱码,.Net获取URL中文参数值的乱码问题解决方法总结

    本文总结分析了.Net获取URL中文参数值的乱码问题解决方法.分享给大家供大家参考,具体如下: 解决方法: 1.设置web.config文件 2.传递中文之前,将要传递的中文参数进行编码,在接收时再进 ...

  3. Oracle 11g中文繁体特殊乱码问题解决

    @](特殊乱码问题解决方式) 遇到问题 最近老大给了一个同事写的操作数据库的程序,因为疫情原因而进行公司员工的锁卡与恢复,需要Oracle环境. 1>在此之前一直做的Excel数据导入工作,简体 ...

  4. 树莓派中文支持(中文显示和中文输入法)

    树莓派(raspberry pi)的原版是没有中文支持的,需安装 startx 后,用 Midori 浏览器 可以浏览网页 浏览www.baidu.com,一堆乱码 安装中文显示支持 第一步,先为终端 ...

  5. gdal mysql乱码_GDAL读取S-57海图数据中文属性值乱码问题解决(续)

    上篇博文中的代码使用了函数wcstombs来进行处理,今天发现GDAL库里面提供了宽字节转单字节的函数,名字叫CPLRecodeFromWChar(这个函数需要libiconv库的支持,也就是在编译G ...

  6. GDAL读取S-57海图数据中文属性值乱码问题解决(续)

    上篇博文中的代码使用了函数wcstombs来进行处理,今天发现GDAL库里面提供了宽字节转单字节的函数,名字叫CPLRecodeFromWChar(这个函数需要libiconv库的支持,也就是在编译G ...

  7. GDAL读取S-57海图数据中文属性值乱码问题解决

    使用GDAL读取S-57海图数据时,对于属性表中的中文属性值读出来是乱码.如图1所示. 图1 S57海图数据中文乱码字段 通过调试代码发现,S-57文件中的中文是按照宽字节存储在文件中,而GDAL在读 ...

  8. 关于php使用sendmail发送邮件时中文附件名乱码问题解决方法

    问题描述:在php使用sendmail发送邮件时中文附件名出现乱码,如图: 原因分析:这是由于编码引起的错误. 解决办法:首先强制进行编码换: substr($file_name,strrpos($f ...

  9. xfce中文字符方块乱码问题解决

    安装locales并配置 sudo apt-get install locales sudo dpkg-reconfigure locales 选择语言编码en_US.UTF8,zh_CN GB231 ...

  10. ubuntu21.04中文冒号变乱码问题解决

    将 /usr/share/fonts/下 Lucida Grande* 删除,注销重新登录就可以了

最新文章

  1. JBOSS 端口修改说明
  2. WINCE Launch函数分析
  3. Fedora 16 正式版专题
  4. Android `AsyncTask`简要分析
  5. GitHub, Google Code, and other
  6. python调用系统命令_linux里面python调用系统命令问题
  7. centos下使用composer安装yii2框架
  8. java如何实现游戏暂停和恢复_Android:游戏循环暂停/恢复问题
  9. 5星评价,1位小数显示
  10. mybatis_07动态SQL_foreach循环
  11. 计算机sci论文怎么写,SCI论文从写作到发表步骤攻略
  12. 2012年8月版:Oracle数据库技术更新…
  13. 华为云文件夹服务器,华为云文件夹服务器
  14. Linux中find命令基本使用方法
  15. 怪兽大乱斗:进入苹果推荐的Creator独立游戏
  16. RocketMQ 之 Broker Server
  17. Web全栈~27.文件和目录的操作
  18. 短信服务之阿里云平台
  19. 爆笑三国故事:张飞流水帐41-50
  20. XStream的分析

热门文章

  1. 开发者详解:端游及手游服务端的常用架构
  2. The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin
  3. 避免使用xlsread()来读取读取excel表格
  4. 仓库货位卡标识牌_仓库状态标志牌管理规程2010版
  5. 2023驱动保护学习 -- 卸载驱动程序
  6. 第三讲 知识抽取与挖掘I
  7. 一款纯VF控制的变频器方案 方案 可提供源码及电路原理图,PCB图。
  8. L1-040 情侣身高差 (10 分)(JAVA)
  9. SQL注入防御之参数加密
  10. 这5种领导,值得员工一生追随!员工和老板都应该读一读