discuz编码转换UTF8与GBK互转完美适合Discuz3.x系列

由于一些网站通信编码的问题不得不把一直使用的网站编码由UTF8转为GBK,在转换过程中在官方看了很多方法,自己也都尝试了一些最后都没有能够成功,数据库的转换一直都是没有大问题,不存在丢失什么的,能看到的问题就是会员设置里边没有任何信息,只有保存。这个问题官方有修复方案在这里就不做过多的说明了。现在主要说的问题就是另一个看不见的数据库问题。造成的问题就是门户首页以及社区首页有DIY数据的地方都卡屏,不显示任何东西,页面卡在第一个有DIY调用模块的地方就不加载了。这个问题也一直排查了很久最后尝试了各种方法,最后决定既然是DIY数据引起的就清空所有的DIY帖子数据表试试,在数据库清空了pre_common_block_item表后整个页面全部加载出来了,问题的点一下就缩小并锁定到这里了,经过反复查证,原来在数据库中有很多序列化数据(serialize),这些序列化数据在不同编码之间经PHP入库和读取的时候会处理成不同的结果,所以导致硬转码后出现这些问题。

我在网上看到的一些资料,对序列化数据的说明是这样的:
   “   Discuz系列对于设置项中数据类型(比如版块设置)采用序列化方式(serialize)保存,读取时使用unserialize()反序列化字符串为数组
序列化这种方式有个致命的缺点:字符集会影响序列化结果
对于这个数组序列化

$s = [1, ‘站长网‘];
echo serialize($s);
复制代码
UTF-8环境下结果为
a:3:{i:0;i:1;i:1;s:15:"站长网";i:2;s:24;}

GB2312环境下结果为
a:3:{i:0;i:1;i:1;s:10:"站长网";i:2;s:24;}

注意看 “站长网”前面的数字,UTF-8下面为15,GB下面为10. 这是因为在UTF-8字符集中中文字长3-4个字节,而在GB/GBK中中日韩问字长都固定为2个字节。至于英文在两种字符集中都占1字节所以序列化长度是固定的
    如此不同的序列化结果产生的兼容性在于不同字符集的discuz版本的数据库中保存的设置项目值是不相同的——在进行字符集版本转移时无法直接导出数据库为目的版本字符集然后再导入。必须对数组类型的设置项进行单独反序列化再使用iconv函数进行字符集转换然后才能序列化入库。遇上数组中还嵌套有数组就更加麻烦了。而如果数组中保存有已经序列化后字符串,那么此数组序列化后就……想着就头大……   ”

      在网上也看了一些其它相关的提示,有一些关于UcHome转码的经验,同样是因为序列化数据的问题需要特殊处理,那既然有办法处理不妨看一下是如何做到的,再参照这些转换Discuz是没有问题的。
     提示是这样的,通过使用PHP的一个函数“addslashes”该函数可用于为存储在数据库中的字符串以及数据库查询语句准备合适的字符串。这样的话我们就可以把存储在数据库中的序列化数据读出再经过该函数转换成适合编码的字符串,然后把这个字符串再入库。
    在网上我也找到了写好的PHP脚本,这个脚本是用来转换uchome的,不过没关系,虽然我的php学的不是太好,但多花点时间还是能做好的。
   通过对数据库字段的逐个查看,找到了存放序列化数据的很多个字段。下面是脚本内容分享给大家,希望对你有用:

---------------------代码文件-----------------------

<?
/**
* 序列化整理脚本,适合uchome2.0、discuz! X2.0、discuz! X3.1,数据库转码后在脚本运行之前请不要运行网站程序(因为网站程序会改写序列化数据),建议此脚本在数据库转换完成后立即执行。
* 此脚本放置与网站根目录,如果放置其他目录请注意修改脚本中config配置文件路径。
**/

//error_reporting(E_ALL);

$step = isset($_GET[‘step‘]) ? $_GET[‘step‘] : ‘start‘;

if($step == ‘start‘) {
        $msg = "<a href=‘serialize.php?step=convert&type=x2‘>Discuz! X2 序列化整理</a>";
        $msg .= "<br/><a href=‘serialize.php?step=convert&type=x31‘>Discuz! X3.1 序列化整理</a>";
        $msg .= "<br/><a href=‘serialize.php?step=convert&type=uch2‘>UCHOME 2.0 序列化整理</a>";
        show_msg($msg);
        
} elseif($step == ‘convert‘) {
        $type = $_GET[‘type‘];
        
        if($type == ‘x2‘ || $type == ‘x31‘) {
                require ‘./config/config_global.php‘;                                // config配置文件路径请确保能连接到目标数据库
                $dbserver   = $_config[‘db‘][‘1‘][‘dbhost‘];
                $dbusername = $_config[‘db‘][‘1‘][‘dbuser‘];
                $dbpassword = $_config[‘db‘][‘1‘][‘dbpw‘];
                $database   = $_config[‘db‘][‘1‘][‘dbname‘];
                $dbcharset  = $_config[‘db‘][‘1‘][‘dbcharset‘];
        } elseif ($type == ‘uch2‘) {
                require ‘.config.php‘;
                $dbserver   = $_SC[‘dbhost‘];
                $dbusername = $_SC[‘dbuser‘];
                $dbpassword = $_SC[‘dbpw‘];
                $database   = $_SC[‘dbname‘];
                $dbcharset  = $_SC[‘dbcharset‘];
        }
        
        if($dbcharset == ‘gbk‘)
            $tocharset = ‘utf8‘;
        else
            $tocharset = ‘gbk‘;
        
        $limit = 100;
        $nextid = 0;
        
        
        $start = !empty($_GET[‘start‘]) ? $_GET[‘start‘] : 0;
        $tid = !empty($_GET[‘tid‘]) ? $_GET[‘tid‘] : 0;
        $arr = getlistarray($type);
        
        $field = $arr[intval($tid)];
        $stable = $field[0];
        $sfield = $field[1];
        $sid        = $field[2];
        $special = $field[3];
        
        $mysql_conn = @mysql_connect("$dbserver", "$dbusername", "$dbpassword") or die("Mysql connect is error.");
    mysql_select_db($database, $mysql_conn);
    mysql_query(‘set names ‘.$dbcharset);
    if($special) {
                $sql = "SELECT $sfield, $sid FROM $stable WHERE $sid > $start ORDER BY $sid ASC LIMIT $limit";
        } else {
                $sql = "SELECT $sfield, $sid FROM $stable";
        }
    
    $query = mysql_query($sql);
    
        while($values = mysql_fetch_array($query)) {
                if($special)
                        $nextid = $values[$sid];
                else
                        $nextid = 0;
                $data = $values[$sfield];
                $id   = $values[$sid];
                $data = preg_replace_callback(‘/s:([0-9]+?):"([\s\S]*?)";/‘,‘_serialize‘,$data);
                $data = addslashes($data);
                mysql_query("UPDATE `$stable` SET `$sfield` = ‘$data‘ WHERE `$sid` = ‘$id‘", $mysql_conn);
        }
        if($nextid)
        {
                show_msg($stable." $sid > $nextid", "serialize.php?step=convert&type=$type&tid=$tid&start=$nextid");
        }
        else
        {        
                $tid++;
                if($tid < count($arr))
                        show_msg($stable." $sid > $nextid", "serialize.php?step=convert&type=$type&tid=$tid&start=0");
                else
                        show_msg(‘转换结束‘, "serialize.php?step=end");
        
        }
        mysql_close($mysql_conn);
} elseif( $step == ‘end‘) {
        show_msg(‘整理结束‘);
}

function _serialize($str) {
        $l = strlen($str[2]);
        return ‘s:‘.$l.‘:"‘.$str[2].‘";‘;
}

function show_msg($message, $url_forward=‘‘, $time = 10, $noexit = 0) {
        if(!empty($url_forward)) {
                $message = "<a href=\"$url_forward\">$message (跳转中...)</a><script>setTimeout(\"window.location.href =‘$url_forward‘;\", $time);</script>";
        }
        print<<<END
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>序列化整理工具</title>
        <body>
        <table>
        <tr><td>$message</td></tr>
        </table>
        </body>
        </html>
END;
}
//以下为需要整理的数据库字段。discuz! x3.1数据库中包含ucenter数据整理,如果你使用的是独立ucenter请在ucenter里(根据自身情况修改表名)再运行一次。
function getlistarray($type) {
        if($type == ‘uch2‘) {
                $list = array(
                        array(‘uchome_data‘, ‘datavalue‘, ‘var‘, FALSE),
                        array(‘uchome_blogfield‘, ‘tag‘, ‘blogid‘, TRUE),
                        array(‘uchome_feed‘, ‘body_template‘, ‘feedid‘, TRUE),
                        array(‘uchome_feed‘, ‘body_data‘, ‘feedid‘, TRUE),
                        array(‘uchome_report‘, ‘uids‘, ‘rid‘, TRUE),
                        array(‘uchome_share‘, ‘body_data‘, ‘sid‘, TRUE),
                        array(‘uchome_userblock‘, ‘blockinfo‘, ‘bid‘, TRUE),
                );
        } elseif($type == ‘x2‘) {
                $list = array(
                                array(‘pre_common_setting‘,‘svalue‘, ‘skey‘, FALSE),
                                array(‘pre_forum_grouplevel‘,‘creditspolicy‘,‘levelid‘, TRUE),
                                array(‘pre_forum_grouplevel‘,‘postpolicy‘,‘levelid‘, TRUE),
                                array(‘pre_forum_grouplevel‘,‘specialswitch‘,‘levelid‘, TRUE),
                                array(‘pre_common_advertisement‘,‘parameters‘,‘advid‘, TRUE),
                                array(‘pre_common_plugin‘,‘modules‘,‘pluginid‘, TRUE),
                                array(‘pre_common_block‘,‘param‘,‘bid‘, TRUE),
                                array(‘pre_common_block_item‘,‘fields‘,‘itemid‘, TRUE),
                                array(‘pre_common_block_style‘,‘template‘,‘styleid‘, TRUE),
                                array(‘pre_common_diy_data‘,‘diycontent‘,‘targettplname‘, TRUE),
                                array(‘pre_common_member_field_forum‘,‘groups‘,‘uid‘, TRUE),
                                array(‘pre_common_member_stat_search‘,‘condition‘,‘optionid‘, TRUE),
                                array(‘pre_common_syscache‘,‘data‘,‘cname‘, TRUE),
                        );
        } elseif($type == ‘x31‘) {
                $list = array(
                                array(‘pre_common_setting‘,‘svalue‘, ‘skey‘, FALSE),
                                array(‘pre_forum_grouplevel‘,‘creditspolicy‘,‘levelid‘, TRUE),
                                array(‘pre_forum_grouplevel‘,‘postpolicy‘,‘levelid‘, TRUE),
                                array(‘pre_forum_grouplevel‘,‘specialswitch‘,‘levelid‘, TRUE),
                                array(‘pre_common_advertisement‘,‘parameters‘,‘advid‘, TRUE),
                                array(‘pre_common_plugin‘,‘modules‘,‘pluginid‘, TRUE),
                                array(‘pre_common_block‘,‘param‘,‘bid‘, TRUE),
                                array(‘pre_common_block‘,‘blockstyle‘,‘bid‘, TRUE),
                                array(‘pre_common_block_item‘,‘fields‘,‘itemid‘, TRUE),
                                array(‘pre_common_block_style‘,‘template‘,‘styleid‘, TRUE),
                                array(‘pre_common_diy_data‘,‘diycontent‘,‘targettplname‘, TRUE),
                                array(‘pre_common_member_field_forum‘,‘groups‘,‘uid‘, TRUE),
                                array(‘pre_common_member_field_home‘,‘blockposition‘,‘uid‘, TRUE),
                                array(‘pre_common_member_field_home‘,‘privacy‘,‘uid‘, TRUE),
                                array(‘pre_common_member_field_home‘,‘acceptemail‘,‘uid‘, TRUE),
                                array(‘pre_common_member_field_home‘,‘magicgift‘,‘uid‘, TRUE),
                                array(‘pre_common_member_verify_info‘,‘field‘,‘vid‘, TRUE),
                                array(‘pre_common_patch‘,‘rule‘,‘serial‘, TRUE),
                                array(‘pre_common_member_stat_search‘,‘condition‘,‘optionid‘, TRUE),
                                array(‘pre_common_plugin‘,‘modules‘,‘pluginid‘, TRUE),
                                array(‘pre_common_member_newprompt‘,‘data‘,‘uid‘, TRUE),
                                array(‘pre_forum_activity‘,‘ufield‘,‘tid‘, TRUE),
                                array(‘pre_forum_forumfield‘,‘creditspolicy ‘,‘fid‘, TRUE),
                                array(‘pre_forum_activity‘,‘formulaperm‘,‘fid‘, TRUE),
                                array(‘pre_forum_activity‘,‘moderators‘,‘fid‘, TRUE),
                                array(‘pre_forum_activity‘,‘modrecommend‘,‘fid‘, TRUE),
                                array(‘pre_forum_activity‘,‘extra‘,‘fid‘, TRUE),
                                array(‘pre_forum_groupfield‘,‘data‘,‘fid‘, TRUE),
                                array(‘pre_forum_medal‘,‘permission‘,‘medalid‘, TRUE),
                                array(‘pre_forum_spacecache‘,‘value‘,‘uid‘, TRUE),
                                array(‘pre_home_feed‘,‘title_data‘,‘feedid‘, TRUE),
                                array(‘pre_home_feed‘,‘body_data‘,‘feedid‘, TRUE),
                                array(‘pre_home_share‘,‘body_data‘,‘sid‘, TRUE),
                                array(‘pre_ucenter_applications‘,‘extra‘,‘appid‘, TRUE),
                                array(‘pre_ucenter_pm_list‘,‘lastmessage‘,‘plid‘, TRUE),
                        );
        }
        return $list;
}
?>

------------------------代码结束----------------------------
保存红色代码线中间的代码另存为serialize.php然后上传到网站根目录选择自己的网站版本进行整合,到此问题解决。

----------------------------------------------------------------------------

另外一种方法:点击“工具”→“数据库”→“备份”→勾选“更多选项”→在“强制字符集”中选择“UTF-8”

时间: 2024-11-05 04:23:13

discuz编码转换UTF8与GBK互转完美适合Discuz3.x系列的相关文章

Linux字符编码转换 UTF8转GB3212

在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现,只不过后者是针对文件的,即将指定文件从一种编码转换为另一种编码.    一.利用iconv函数族进行编码转换    iconv函数族的头文 在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现,只不过后者是针对文件的,即将指定文件从一种编码转换为另一种编码.    一.利用iconv函数族进行编码转换    iconv函数族的头文件是iconv.h,使用前

黄聪:C#中WebClient自动判断编码是UTF-8还是GBK,并且有超时判断功能

public class WebDownload : WebClient { private int _timeout; /// <summary> /// 超时时间(毫秒) /// </summary> public int Timeout { get { return _timeout; } set { _timeout = value; } } public WebDownload() { this._timeout = 60000; } public WebDownload

C# 编码转换 UTF8转GB2312 GB2312转UTF8

来源:http://www.cnblogs.com/mahatmasmile/p/3467495.html/// <summary> /// GB2312转换成UTF8 /// </summary> /// <param name="text"></param> /// <returns></returns> public static string gb2312_utf8(string text) { //声明字

关于utf8 unicode gbk 编码乱码汇总

首先从一个问题说起: 插入一个中文到blob类型(mysql编码是utf-unicode-ci). insert into  blobtype(data) values('中文你好') 赋值数据显示为: 涓枃浣犲ソ * 这是为什么? blob存进去的出来为什么不是中文你好,因为编码的问题,我们复制后直接显示是asci编码.转成utf8编码就可以看到“中文你好”了. unicode和utf8不是一个东西. 中文你好 这4个字 中文转unicdoe是\u4e2d\u6587\u4f60\u597d

Unicode、ANSI、UTF-8、GBK详谈

最近在写网络通信上的一些东西,快被这些编码格式搞崩溃了. 一.什么是编码 编码是对现有"符号"进行转化,可以存储在计算机中,在没有计算机时,我们的使用的"符号",都是手写的,我们的大脑对其编码,这样我们就能记住和识别.但计算机只能存储电信号,即二进制.所以,我们需要对其编码,能使计算机储存. 各个国家和地区所制定了不同 ANSI 编码标准中,都只规定了各自语言所需的"字符".这样就不利于交流,所以就有了Unicode编码. 名词解析: 1.ANS

convmv编码转换工具详解

convmv编码转换工具详解文件名转码的工具--convmv,convmv能帮助我们很容易地对一个文件,一个目录下所有文件进行编码转换,比如gbk转为utf8等.安装 yum install convmv语法:convmv [options] FILE(S) ... DIRECTORY(S)主要选项:1.-f ENCODING指定目前文件名的编码,如-f gbk2.-t ENCODING指定将要转换成的编码,如-f utf-83.-r递归转换目录下所有文件名4.--list列出所有支持的编码5.

修改数据库mysql字符编码为UTF8

Mysql数据库是一个开源的数据库,应用非常广泛.以下是修改mysql数据库的字符编码的操作过程. 步骤1:查看当前的字符编码方法 mysql> show variables like'character%'; +--------------------------+----------------------------+ |Variable_name |Value | +--------------------------+----------------------------+ |cha

gbk转utf-8 iconv 编码转换

linux下面有时候 字符需要进行编码转换(爬虫将gbk转为utf-8编码...),一般可以选择iconv函数. 终端下面  输入 man 3 iconv 得到  iconv函数的使用方法. 个人看习惯了,msdn文档之后感觉linux下面的文档的看的不是那么爽了. 使用iconv函数进行转码,一般使用三个函数:iconv_open  . iconv  .iconv_close三个函数. iconv_t iconv_open(const char* tocode,const char* from

GBK编码和UTF-8编码互转的大坑

这几天遇到一个BUG,问题很简单,解决却花了3.4天,特意记录下来. linux环境下,将默认编码设置为GBK以后,运行GBK编码的脚本,调用一个Java的jar包,然后总jar包中返回GBK字符串.但是不知道是哪里出了问题,返回的参数一直是问号乱码. 放上脚本代码: #!/bin/bash #str="\"$1 $2 $3\"" str="\"http://iap.zh.gmcc.net/WebService/Notify.asmx chenl