现在的位置: 首页 > 综合 > 正文

PhpNewsReader—不使用iconv进行字符编码转换

2013年01月31日 ⁄ 综合 ⁄ 共 1928字 ⁄ 字号 评论关闭

服务器上是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);
    }
}

抱歉!评论已关闭.