昔、GB コードを UTF-8 に変換する関数を見つけ、それを GB と UNICODE の比較表 (gb2312.txt) と併用して、GD で漢字を出力しました。後で調べたところ、出力する内容に欧文文字が含まれる場合、混乱が生じることが分かりました。後で修正されたコードを見つけて問題を解決しました。 2 つの機能を比較分析すると次のようになります。
まず、これは UNICODE を UTF-8 エンコードに変換する関数です。この部分は変更前と変更後では変わりません。
function u2utf8($c)
{
for($i=0 ;$i
if ($c $str.=$c ;
}
else if ($c < 0x800) {
$str.=(0xC0 | $c>>6);
$str.=(0x80 | $c & 0x3F );
}
else if ($c < 0x10000) {
$str.=(0xE0 | $c>>12);
$str.=(0x80 | $c> >6 & 0x3F);
$str.=(0x80 | $c & 0x3F);
}
else if ($c $str.=(0xF0 | $c & 0x3F) $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 に変換します。いくつかのバイトはこれらの 3 つのステップはループ内で完了します。特に、複数のバイトを UTF-8 文字に結合するステップは、その文字が西洋文字に属するか中国語文字に属するかを判断するために使用されます。それに応じて、1 バイトまたは 3 バイトをインターセプトすることが決定されます。したがって、結果は正しいです!