首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實現 GB2312 與 Unicode 雙向編碼轉換完整指南

     編輯:PHP 綜合知識

前言

在早期 PHP 開發中,處理中文編碼轉換是常見挑戰。本文詳細介紹如何使用 PHP 實現 GB2312(簡體中文標準編碼)與 Unicode 數值實體(如 `全`)之間的雙向轉換,並提供多種實現方案供參考。

方案一:使用 iconv + 自定義 UTF-8 轉 Unicode 函數

PHP 4.3.1 後內建 iconv 函數,可高效處理編碼轉換。但需自行實現 UTF-8 到 Unicode 碼位的轉換。

GB2312 轉 Unicode 實體

<?php
$text = "全天候自動聚焦";
// 使用正則匹配雙字節字符(GB2312 範圍)
preg_match_all("/[\x80-\xff]?./", $text, $ar);
foreach ($ar[0] as $v) {
    // 先轉 UTF-8,再轉 Unicode 碼位
    echo "&#".utf8_unicode(iconv("GB2312", "UTF-8", $v)).";";
}

// UTF-8 字符轉 Unicode 碼位(十進制)
function utf8_unicode($c) {
    switch (strlen($c)) {
        case 1: return ord($c);
        case 2:
            $n = (ord($c[0]) & 0x3f) << 6;
            $n += ord($c[1]) & 0x3f;
            return $n;
        case 3:
            $n = (ord($c[0]) & 0x1f) << 12;
            $n += (ord($c[1]) & 0x3f) << 6;
            $n += ord($c[2]) & 0x3f;
            return $n;
        case 4:
            $n = (ord($c[0]) & 0x0f) << 18;
            $n += (ord($c[1]) & 0x3f) << 12;
            $n += (ord($c[2]) & 0x3f) << 6;
            $n += ord($c[3]) & 0x3f;
            return $n;
    }
}
?>

Unicode 實體轉 GB2312

<?php
$str = "TTL全天候自动聚焦";
// 使用正則替換,配合 eval 執行動態代碼
$str = preg_replace("|&#([0-9]{1,5});|", "\".u2utf82gb(\\1).\"", $str);
$str = "\$str=\"$str\";";
eval($str);
echo $str; // 輸出:TTL全天候自動聚焦

function u2utf82gb($c) {
    $str = "";
    if ($c < 0x80) {
        $str .= $c;
    } elseif ($c < 0x800) {
        $str .= chr(0xC0 | $c >> 6);
        $str .= chr(0x80 | $c & 0x3F);
    } elseif ($c < 0x10000) {
        $str .= chr(0xE0 | $c >> 12);
        $str .= chr(0x80 | $c >> 6 & 0x3F);
        $str .= chr(0x80 | $c & 0x3F);
    } elseif ($c < 0x200000) {
        $str .= chr(0xF0 | $c >> 18);
        $str .= chr(0x80 | $c >> 12 & 0x3F);
        $str .= chr(0x80 | $c >> 6 & 0x3F);
        $str .= chr(0x80 | $c & 0x3F);
    }
    return iconv('UTF-8', 'GB2312', $str);
}
?>

方案二:通用 unescape 函數(支援多種編碼格式)

此函數可同時處理 `%uXXXX`、`&#xXXXX;`、`&#DDDD;` 三種格式,利用 pack 和 iconv 實現 UCS-2 到 GB2312 轉換。

function unescape($str) {
    $str = rawurldecode($str);
    preg_match_all("/(?:%u.{4})|&#x.{4};|&#\d+;|.+/U", $str, $r);
    $ar = $r[0];
    foreach ($ar as $k => $v) {
        if (substr($v, 0, 2) == "%u") {
            $ar[$k] = iconv("UCS-2", "GB2312", pack("H4", substr($v, -4)));
        } elseif (substr($v, 0, 3) == "&#x") {
            $ar[$k] = iconv("UCS-2", "GB2312", pack("H4", substr($v, 3, -1)));
        } elseif (substr($v, 0, 2) == "&#") {
            $ar[$k] = iconv("UCS-2", "GB2312", pack("n", substr($v, 2, -1)));
        }
    }
    return join("", $ar);
}

$str = "TTL全天候自动聚焦";
echo unescape($str); // 輸出:TTL全天候自動聚焦

方案三:JavaScript 前端互轉工具

提供一個完整的 HTML 頁面,包含字符與 Unicode 實體雙向轉換功能,支援正向/反向模式切換。

<script language="JavaScript1.2">
function Str2Unicode(str) {
    var arr = [];
    for (var i = 0; i < str.length; i++) {
        arr[i] = "&#" + str.charCodeAt(i) + ";";
    }
    return arr.join("");
}

function Unicode2oStr(str) {
    var re = /&#[\da-fA-F]{1,5};/ig;
    var arr = str.match(re);
    if (!arr) return "";
    for (var i = 0; i < arr.length; i++) {
        arr[i] = String.fromCharCode(arr[i].replace(/[&#;]/g, ""));
    }
    return arr.join("");
}
// ... 表單交互代碼省略 ...
</script>

方案四:字符碼位範圍查看器

內建常用字符集範圍按鈕(半角、全角、中文、日文、韓文等),可自定義範圍查看字符實體。

<script>
function showUni(min, max) {
    show.document.open();
    show.document.writeln("<style>body{font-size:9pt;word-break:break-all;}</style>");
    show.document.writeln(min + " - " + max + "<br><br>");
    for (var i = min; i <= max; i++) {
        show.document.write("&#" + i + ";");
    }
    show.document.close();
}
</script>
<input type=button value="半角" onclick=showUni(32,126)>
<input type=button value="全角" onclick=showUni(65281,65374)>
<input type=button value="中文1" onclick=showUni(19968,40869)>
<!-- 更多按鈕省略 -->

方案五:查表法 GB2312 轉 UTF-8(歷史參考)

早期無 iconv 時使用映射表文件 gb2312.txt 進行轉換,現已不推薦,僅供了解原理。

function gb2utf8($gb) {
    if (!trim($gb)) return $gb;
    $filename = "gb2312.txt";
    $tmp = file($filename);
    $codetable = [];
    while (list($key, $value) = each($tmp)) {
        $codetable[hexdec(substr($value, 0, 6))] = substr($value, 7, 6);
    }
    // ... 轉換邏輯省略 ...
    return $utf8;
}

總結與建議

  • 現代專案:優先使用 PHP 內建 mb_convert_encoding 或 iconv,配合 UTF-8 統一編碼。
  • 維護舊系統:上述方案可解決 GB2312 與 Unicode 實體互轉需求。
  • 安全提示:方案一使用 eval 存在風險,實際部署請改用 preg_replace_callback。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved