服务器上是apache2.2.4 + php4.4.6,使用php4内置的mysql模块。
任务是修改一个管理系统,使查询数据能够导出到excel中去,我使用pear来完成导出到excel的工作。终端用户都使用中文IE,都是GBK编码,但是数据库里的数据是UTF8编码,所以需要做编码转换。问题是:服务器上的php4没有iconv模块。
解决思路一:让excel使用utf8编码,使用:header("Content-type: application/vnd.ms-excel; charset=UTF-8"),但由于是二进制数据,这里的charset不能对结果产生影响。
解 决思路二:给服务器php安装iconv模块。但结果是:安装php4只产生libphp4.a而没有libphp4.so,google一下发现这是 php的bug,但是用了最新的php4的代码也还是有这个问题,也有人说是apache编译参数不对,重新编译apache,还是有问题。安装 php5,php5中已经去掉了内置的mysql模块,需要单独安装mysql,这可能会出现版本冲突问题而影响服务器上的众多网站,放弃。
解决思路三:尝试寻找一种不使用iconv完成编码转换任务的方法。搜索到了Php News Reader项目。这个项目的一个附加模块就是完全不使用iconv,而通过查编码转换表进行编码转换。
Php News Reader项目的主页:http://pnews.urdada.net/
下载Php News Reader的源代码:svn co https://pnews.svn.sourceforge.net/svnroot/pnews/trunk/pnews
在源代码的languages/下面有很多转换表,这里需要用到的是unicode-gb.tab,在language.inc.php文件中,定义了所有编码转换函数,我们需要的utf8转到gbk的函数是:
function u2g( $instr ) {
$fp = fopen( 'language/unicode-gb.tab', 'r' );
$len = strlen($instr);
$outstr = '';
for( $i = $x = 0 ; $i < $len ; $i++ ) {
$b1 = ord($instr[$i]);
if( $b1 < 0x80 ) {
$outstr[$x++] = chr($b1);
# printf( "[%02X]", $b1);
}
elseif( $b1 >= 224 ) { # 3 bytes UTF-8
$b1 -= 224;
$b2 = ($i+1 >= $len) ? 0 : ord($instr[$i+1]) - 128;
$b3 = ($i+2 >= $len) ? 0 : ord($instr[$i+2]) - 128;
$i += 2;
$uc = $b1 * 4096 + $b2 * 64 + $b3 ;
fseek( $fp, $uc * 2 );
$gb = fread( $fp, 2 );
$outstr[$x++] = $gb[0];
$outstr[$x++] = $gb[1];
# printf( "[%02X%02X]", ord($gb[0]), ord($gb[1]));
}
elseif( $b1 >= 192 ) { # 2 bytes UTF-8
printf( "[%02X%02X]", $b1, ord($instr[$i+1]) );
$b1 -= 192;
$b2 = ($i+1>=$len) ? 0 : ord($instr[$i+1]) - 128;
$i++;
$uc = $b1 * 64 + $b2 ;
fseek( $fp, $uc * 2 );
$gb = fread( $fp, 2 );
$outstr[$x++] = $gb[0];
$outstr[$x++] = $gb[1];
# printf( "[%02X%02X]", ord($gb[0]), ord($gb[1]));
}
}
fclose($fp);
if( $instr != '' ) {
# echo '##' . $instr . " becomes " . join( '', $outstr) . "<br>/n";
return join( '', $outstr);
}
}