変換
昔、GB コードを UTF-8 に変換する関数を見つけ、それを GB と UNICODE の比較表 (gb2312.txt) と併用して、GD で漢字を出力しました。後で調べたところ、出力する内容に欧文文字が含まれる場合、混乱が生じることが分かりました。後で修正されたコードを見つけて問題を解決しました。 2 つの機能を比較分析すると次のようになります。
まず、UNICODEをUTF-8エンコードに変換する関数です。
function u2utf8($c)
{
for($i=0;$i<) この部分は変更前と変更後では変わりません。 ;count($c); $i++)
$str="";
if ($c $str.=$c;
}
else if ($c $ str.=(0xC0 | $ c>>6);
$str.=(0x80 | $c & 0x3F);
}
else if ($c $str.=(0xE0 | $ c>>12);
$str.=(0x80 | $c>>6 & 0x3F);
$str.=(0x80 | $c & 0x3F);
}
else if ($c $str.= (0xF0 | $c>>18);
$str.=(0x80 | $c>>12 & 0x3F);
$str.=(0x80 | $c>>6 & 0x3F);
$str .=(0x80 | $c & 0x3F);
}
return $str;
}
これは、文字が異なるものに属すると判断することにより、UTF-8 エンコード規則に完全に準拠しています。 UNICODE エンコード セグメント範囲を指定し、さまざまなシフトと加算のビット単位 AND 演算を実行して UTF-8 エンコードに変換します。このルールの詳細については、http://www.utf8.org/ の手順を参照してください。
上記のu2utf8関数を呼び出した、GBを修正前のUTF-8エンコーディングに変換する関数です。
function gb2utf8($gb) /* 悲しいことに www.phpx.com によって書かれたプログラム */
{
if(!trim($gb))
return $gb;
$filename="gb2312.txt";
$tmp =file($filename);
$codetable=array();
while(list($key,$value)=each($tmp))
$codetable[hexdec(substr($value,0,6))] =substr($value,7,6);
$utf8="";
while($gb)
{
if (ord(substr($gb,0,1))>127)
{
$this =substr($gb,0,2);
$gb=substr($gb,2,strlen($gb));
$utf8.=u2utf8(hexdec($codetable[hexdec(bin2hex($this))) - 0x8080]));
}
else
{
$gb=substr($gb,1,strlen($gb));
$utf8.=u2utf8(substr($gb,0,1));
}
}
$ret="";
for($i=0;$i
return $ret;
}
関数の while ループ部分は、「検索テーブル」に従って中国語の文字を 1 つずつ UNICODE に変換し、それから u2utf8 関数を通じて UTF-8 に変換します。しかし、このことから、while ループが終了した後、for ループを使用して 3 バイトごとに UTF-8 文字が合成されることがわかります (http://www.utf8.org/ のルールの説明を参照してください。各漢字はUTF-8 エンコードは 3 バイトです)、西欧文字は考慮されません (西欧文字の UTF-8 エンコードは 1 バイトです)。そのため、出力する内容の先頭に欧文や欧文の中に漢字が混在している場合、UTF-8に変換した後、「3バイトごとのインターセプト」方式により切り取られて文字化けしてしまいます。文字。
以下は変更された関数です:
function gb2utf8($gb) /* 悲しいことに agun によって変更されたプログラムが書かれました */
{
if(!trim($gb))
return $gb;
$filename= gb2312.txt";
$tmp=file($filename);
$codetable=array();
while(list($key,$value)=each($tmp))
$codetable[hexdec(substr($ value,0,6))]=substr($value,7,6);
$ret="";
$utf8="";
while($gb)
{
if (ord(substr($ gb,0,1))>127)
{
$this=substr($gb,0,2);
$gb=substr($gb,2,strlen($gb));
$utf8=u2utf8 (hexdec($codetable[hexdec(bin2hex($this))-0x8080]));
for($i=0;$i
}
else
{
$ret.=substr($gb,0,1);
$gb=substr($gb,1,strlen($gb));
}
}
return $ret;
}
変更された関数は、GB を UNICODE に変換し、UNICODE を UTF-8 に変換し、いくつかのバイトを UTF-8 文字に変換します。これらの 3 つのステップ、特に次のステップで完了します。 UTF-8 の文字に複数のバイトを合成し、その文字が欧文に属するか漢字に属するかを判断する条件分岐に置かれ、これに基づいて 1 バイトまたは 3 バイトをインターセプトするかどうかが決定されます。したがって、結果は正しいです!