請注意,utf8_encode 只會將以 ISO-8859-1 編碼的字串轉換為 UTF-8。更適合它的名稱應該是「iso88591_to_utf8」。如果您的文字不是以 ISO-8859-1 編碼,則不需要此函式。如果您的文字已經是 UTF-8 格式,則不需要此函式。事實上,將此函式套用至非以 ISO-8859-1 編碼的文字很可能只會損毀該文字。
如果您需要將文字從任何編碼轉換為任何其他編碼,請改用 iconv()。
(PHP 4, PHP 5, PHP 7, PHP 8)
utf8_encode — 將字串從 ISO-8859-1 轉換為 UTF-8
自 PHP 8.2.0 起,此函式已過時。強烈不建議依賴此函式。
此函式將字串 string
從 ISO-8859-1
編碼轉換為 UTF-8
。
注意:
此函式不會嘗試猜測提供的字串的目前編碼,它假設它是以 ISO-8859-1(也稱為「Latin 1」)編碼,並轉換為 UTF-8。由於每個位元組序列都是有效的 ISO-8859-1 字串,這永遠不會導致錯誤,但如果預期的編碼不同,則不會產生有用的字串。
許多標記為使用
ISO-8859-1
字元編碼的網頁實際上使用相似的Windows-1252
編碼,而且網頁瀏覽器會將ISO-8859-1
網頁解譯為Windows-1252
。Windows-1252
具有額外的可列印字元,例如歐元符號(€
)和彎引號(“
”
),而不是某些ISO-8859-1
控制字元。如果需要Windows-1252
轉換,則此函式不會正確轉換這些Windows-1252
字元。請使用不同的函式。
字串
一個 ISO-8859-1 字串。
傳回 string
的 UTF-8 翻譯。
版本 | 描述 |
---|---|
8.2.0 | 此函式已過時。 |
7.2.0 | 此函式已從 XML 擴充功能移至 PHP 的核心。在之前的版本中,只有在安裝 XML 擴充功能時才可用。 |
範例 #1 基本範例
<?php
// 將字串 'Zoë' 從 ISO 8859-1 轉換為 UTF-8
$iso8859_1_string = "\x5A\x6F\xEB";
$utf8_string = utf8_encode($iso8859_1_string);
echo bin2hex($utf8_string), "\n";
?>
上面的範例會輸出
5a6fc3ab
注意:過時與替代方案
此函式自 PHP 8.2.0 起已過時,並將在未來版本中移除。應檢查現有的用法,並以適當的替代方案取代。
使用 mb_convert_encoding() 可達到類似的功能,此函式支援 ISO-8859-1 和許多其他字元編碼。
<?php
$iso8859_1_string = "\xEB"; // ISO-8859-1 中的 'ë' (帶分音符號的 e)
$utf8_string = mb_convert_encoding($iso8859_1_string, 'UTF-8', 'ISO-8859-1');
echo bin2hex($utf8_string), "\n";
$iso8859_7_string = "\xEB"; // ISO-8859-7 中的同一個字串表示 'λ' (希臘小寫 lambda)
$utf8_string = mb_convert_encoding($iso8859_7_string, 'UTF-8', 'ISO-8859-7');
echo bin2hex($utf8_string), "\n";
$windows_1252_string = "\x80"; // Windows-1252 中的 '€' (歐元符號),但在 ISO-8859-1 中則沒有
$utf8_string = mb_convert_encoding($windows_1252_string, 'UTF-8', 'Windows-1252');
echo bin2hex($utf8_string), "\n";
?>上面的範例會輸出
c3ab cebb e282ac根據安裝的擴充功能,其他可能可用的選項是 UConverter::transcode() 和 iconv()。
以下所有結果都相同
<?php
$iso8859_1_string = "\x5A\x6F\xEB"; // 'Zoë' in ISO-8859-1
$utf8_string = utf8_encode($iso8859_1_string);
echo bin2hex($utf8_string), "\n";
$utf8_string = mb_convert_encoding($iso8859_1_string, 'UTF-8', 'ISO-8859-1');
echo bin2hex($utf8_string), "\n";
$utf8_string = UConverter::transcode($iso8859_1_string, 'UTF8', 'ISO-8859-1');
echo bin2hex($utf8_string), "\n";
$utf8_string = iconv('ISO-8859-1', 'UTF-8', $iso8859_1_string);
echo bin2hex($utf8_string), "\n";
?>上面的範例會輸出
5a6fc3ab 5a6fc3ab 5a6fc3ab 5a6fc3ab
請注意,utf8_encode 只會將以 ISO-8859-1 編碼的字串轉換為 UTF-8。更適合它的名稱應該是「iso88591_to_utf8」。如果您的文字不是以 ISO-8859-1 編碼,則不需要此函式。如果您的文字已經是 UTF-8 格式,則不需要此函式。事實上,將此函式套用至非以 ISO-8859-1 編碼的文字很可能只會損毀該文字。
如果您需要將文字從任何編碼轉換為任何其他編碼,請改用 iconv()。
以下是一些解決 Steven 在先前註解中描述的問題的程式碼:
<?php
/* 此結構會將 ISO-8859-1 與 Windows-1252 之間的差異編碼,
作為從某些 ISO-8859-1 控制字元的 UTF-8 編碼到
Windows-1252 在對等碼點放置的非控制字元的 UTF-8 編碼的對應。 */
$cp1252_map = array(
"\xc2\x80" => "\xe2\x82\xac", /* 歐元符號 */
"\xc2\x82" => "\xe2\x80\x9a", /* 單引號下 9 引號 */
"\xc2\x83" => "\xc6\x92", /* 帶鉤的拉丁小型字母 F */
"\xc2\x84" => "\xe2\x80\x9e", /* 雙引號下 9 引號 */
"\xc2\x85" => "\xe2\x80\xa6", /* 水平省略符號 */
"\xc2\x86" => "\xe2\x80\xa0", /* 劍號 */
"\xc2\x87" => "\xe2\x80\xa1", /* 雙劍號 */
"\xc2\x88" => "\xcb\x86", /* 修飾字母迴旋重音符號 */
"\xc2\x89" => "\xe2\x80\xb0", /* 千分號 */
"\xc2\x8a" => "\xc5\xa0", /* 帶抑揚符號的拉丁大寫字母 S */
"\xc2\x8b" => "\xe2\x80\xb9", /* 單左指向角引號 */
"\xc2\x8c" => "\xc5\x92", /* 拉丁大寫連字 OE */
"\xc2\x8e" => "\xc5\xbd", /* 帶抑揚符號的拉丁大寫字母 Z */
"\xc2\x91" => "\xe2\x80\x98", /* 左單引號 */
"\xc2\x92" => "\xe2\x80\x99", /* 右單引號 */
"\xc2\x93" => "\xe2\x80\x9c", /* 左雙引號 */
"\xc2\x94" => "\xe2\x80\x9d", /* 右雙引號 */
"\xc2\x95" => "\xe2\x80\xa2", /* 項目符號 */
"\xc2\x96" => "\xe2\x80\x93", /* 恩破折號 */
"\xc2\x97" => "\xe2\x80\x94", /* 艾姆破折號 */
"\xc2\x98" => "\xcb\x9c", /* 小型波浪符號 */
"\xc2\x99" => "\xe2\x84\xa2", /* 商標符號 */
"\xc2\x9a" => "\xc5\xa1", /* 帶抑揚符號的拉丁小型字母 S */
"\xc2\x9b" => "\xe2\x80\xba", /* 單右指向角引號 */
"\xc2\x9c" => "\xc5\x93", /* 拉丁小型連字 OE */
"\xc2\x9e" => "\xc5\xbe", /* 帶抑揚符號的拉丁小型字母 Z */
"\xc2\x9f" => "\xc5\xb8" /* 帶分音符的拉丁大寫字母 Y */
);
function cp1252_to_utf8($str) {
global $cp1252_map;
return strtr(utf8_encode($str), $cp1252_map);
}
?>
我的 utf8_encode_deep 版本,
如果您需要一個在不變更原始值的情況下傳回值的版本。
/**
* 將任何內容轉換為 UTF-8
* @param mixed $var 您要轉換的變數。
* @param boolean $deep 深度轉換?(*預設:TRUE)。
* @return mixed
*/
function anything_to_utf8($var,$deep=TRUE){
if(is_array($var)){
foreach($var as $key => $value){
if($deep){
$var[$key] = anything_to_utf8($value,$deep);
}elseif(!is_array($value) && !is_object($value) && !mb_detect_encoding($value,'utf-8',true)){
$var[$key] = utf8_encode($var);
}
}
return $var;
}elseif(is_object($var)){
foreach($var as $key => $value){
if($deep){
$var->$key = anything_to_utf8($value,$deep);
}elseif(!is_array($value) && !is_object($value) && !mb_detect_encoding($value,'utf-8',true)){
$var->$key = utf8_encode($var);
}
}
return $var;
}else{
return (!mb_detect_encoding($var,'utf-8',true))?utf8_encode($var):$var;
}
}
如果您需要一個將字串陣列轉換為 utf8 編碼字串陣列的函式,則此函式可能對您有用
<?php
function utf8_string_array_encode(&$array){
$func = function(&$value,&$key){
if(is_string($value)){
$value = utf8_encode($value);
}
if(is_string($key)){
$key = utf8_encode($key);
}
if(is_array($value)){
utf8_string_array_encode($value);
}
};
array_walk($array,$func);
return $array;
}
?>
為了方便參考,指出以下內容可能會很有啟發性
utf8_encode($s)
實際上與
recode_string('latin1..utf8', $s)
和
iconv('iso-8859-1', 'utf-8', $s)
相同。也就是說,utf8_encode 是字元集轉換的特殊案例。
如果您的字串要轉換為 utf-8 的編碼不是 iso-8859-1(例如 iso-8859-2(波蘭語/克羅埃西亞語)),則您應該改用 recode_string() 或 iconv(),而不是嘗試設計複雜的 str_replace 陳述式。
遍歷巢狀陣列/物件並將所有字串進行 UTF-8 編碼。
<?php
// 用法
class Foo {
public $somevar = 'whoop whoop';
}
$structure = array(
'object' => (object) array(
'entry' => 'hello wörld',
'another_array' => array(
'string',
1234,
'another string'
)
),
'string' => 'foo',
'foo_object' => new Foo
);
utf8_encode_deep($structure);
// $structure 現在是 UTF-8 編碼
print_r($structure);
// 函式
function utf8_encode_deep(&$input) {
if (is_string($input)) {
$input = utf8_encode($input);
} else if (is_array($input)) {
foreach ($input as &$value) {
utf8_encode_deep($value);
}
unset($value);
} else if (is_object($input)) {
$vars = array_keys(get_object_vars($input));
foreach ($vars as $var) {
utf8_encode_deep($input->$var);
}
}
}
?>
如果您正在尋找一個函式來將特殊字元替換為十六進制 UTF-8 值(例如,為了符合 Web 服務安全性/WSS4J 標準),您可以使用此函式
$textstart = "Größe";
$utf8 ='';
$max = strlen($txt);
for ($i = 0; $i < $max; $i++) {
if ($txt{i} == "&"){
$neu = "&x26;";
}
elseif ((ord($txt{$i}) < 32) or (ord($txt{$i}) > 127)){
$neu = urlencode(utf8_encode($txt{$i}));
$neu = preg_replace('#\%(..)\%(..)\%(..)#','&#x\1;&#x\2;&#x\3;',$neu);
$neu = preg_replace('#\%(..)\%(..)#','&#x\1;&#x\2;',$neu);
$neu = preg_replace('#\%(..)#','&#x\1;',$neu);
}
else {
$neu = $txt{$i};
}
$utf8 .= $neu;
} // for $i
$textnew = $utf8;
在這個範例中,$textnew 將會是 "Größe"
我正在尋找一個類似於 Javascript 的 unescape() 函式。在大多數情況下,使用 url_decode() 函式是可以的,但如果字串中有 UTF 字元則不行。它們會被轉換為 %uXXXX 實體,而 url_decode() 無法處理這些實體。
我在網路上搜尋並找到了一個函式,它可以將這些實體轉換為您的瀏覽器可以正確顯示的 HTML 實體 (&#xxx;)。如果您可以接受這一點,可以在這裡找到該函式:http://pure-essence.net/stuff/code/utf8RawUrlDecode.phps
但這對我來說並不好,因為我需要一個我的字元集中的字串來進行一些比較和其他操作。因此,我修改了上述函式,並結合這裡其他筆記中提到的 code2utf() 函式,我成功實現了我的目標。
<?php
/**
* 函式將 Javascript 逸出的字串轉換回具有指定字元集的字串(預設為 UTF-8)。
* 修改自 http://pure-essence.net/stuff/code/utf8RawUrlDecode.phps 的函式
*
* @param string $source 使用 Javascript 的 escape() 函式逸出的字串
* @param string $iconv_to 目標字元集將在 iconv 函式中用作第二個參數。預設為 UTF-8。
* @return string
*/
function unescape($source, $iconv_to = 'UTF-8') {
$decodedStr = '';
$pos = 0;
$len = strlen ($source);
while ($pos < $len) {
$charAt = substr ($source, $pos, 1);
if ($charAt == '%') {
$pos++;
$charAt = substr ($source, $pos, 1);
if ($charAt == 'u') {
// 我們得到了一個 Unicode 字元
$pos++;
$unicodeHexVal = substr ($source, $pos, 4);
$unicode = hexdec ($unicodeHexVal);
$decodedStr .= code2utf($unicode);
$pos += 4;
}
else {
// 我們有一個逸出的 ASCII 字元
$hexVal = substr ($source, $pos, 2);
$decodedStr .= chr (hexdec ($hexVal));
$pos += 2;
}
}
else {
$decodedStr .= $charAt;
$pos++;
}
}
if ($iconv_to != "UTF-8") {
$decodedStr = iconv("UTF-8", $iconv_to, $decodedStr);
}
return $decodedStr;
}
/**
* 函式將 UTF 字元的數字轉換為該字元。
* 函式取自:http://sk2.php.net/manual/en/function.utf8-encode.php#49336
*
* @param int $num
* @return utf8char
*/
function code2utf($num){
if($num<128)return chr($num);
if($num<2048)return chr(($num>>6)+192).chr(($num&63)+128);
if($num<65536)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
return '';
}
?>
這個函式可能有用於編碼陣列的鍵和值 [並先檢查是否已經是 UTF 格式]
<?php
public static function to_utf8($in)
{
if (is_array($in)) {
foreach ($in as $key => $value) {
$out[to_utf8($key)] = to_utf8($value);
}
} elseif(is_string($in)) {
if(mb_detect_encoding($in) != "UTF-8")
return utf8_encode($in);
else
return $in;
} else {
return $in;
}
return $out;
}
?>
希望這能有所幫助。
[danbrown AT php DOT net 的註解:原始函式由 (cmyk777 AT gmail DOT com) 於 2009 年 1 月 28 日撰寫。]
我嘗試了很多方法,但這似乎是將任何字串轉換為正確 UTF-8 的最終保險方法。
<?php
function _convert($content) {
if(!mb_check_encoding($content, 'UTF-8')
OR !($content === mb_convert_encoding(mb_convert_encoding($content, 'UTF-32', 'UTF-8' ), 'UTF-8', 'UTF-32'))) {
$content = mb_convert_encoding($content, 'UTF-8');
if (mb_check_encoding($content, 'UTF-8')) {
// log('Converted to UTF-8');
} else {
// log('Could not converted to UTF-8');
}
}
return $content;
}
?>
// 讀取檔案 story.txt ascii (如同在鍵盤上輸入)
// 使用 utf8 編碼將其轉換為喬治亞字符
// 如果我沒理解錯的話(?) 就像在喬治亞電腦上輸入時一樣
// 將其輸出為 html 檔案
//
// http://www.comweb.nl/keys_to_georgian.html
// http://www.comweb.nl/keys_to_georgian.php
// http://www.comweb.nl/story.txt
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<TITLE>按鍵對應 Unicode 編碼</TITLE>
// 這個 meta 標籤是必需的
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
// 請注意,sylfean 字體似乎是 Windows XP 的標準安裝字體
// 它支援喬治亞語
<style TYPE="text/css">
<!--
body {font-family:sylfaen; }
-->
</style>
</HEAD>
<BODY>
<?
$eng=array(97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,87,82,84,83,
67,74,90);
$geo=array(4304,4305,4330,4307,4308,4324,4306,4336,4312,4335,4313,
4314,4315,4316,4317,4318,4325,4320,4321,4322,4323,4309,
4332,4334,4327,4310,4333,4326,4311,4328,4329,4319,4331,
91,93,59,39,44,46,96);
$fc=file("story.txt");
foreach($fc as $line)
{
$spacestart=1;
for ($i=0; $i<strlen($line); $i+=1)
{
$character=ord(substr($line,$i,1));
$found=0;
for ($k=0; $k<count($eng); $k+=1)
{
if ($eng[$k]==$character)
{
print code2utf( $geo[$k] );
$found=1;
}
}
if ($found==0)
{
if ($character==126 || $character==32 || $character==10 || $character==9)
{
if ($character==9) { print ' '; }
if ($character==10) { print "<BR>\n"; }
if ($character==32)
{
if ($spacestart==1) {print ' '; } else { print " "; }
}
if ($character==126){ print "~"; }
} else
{
print substr($line,$i,1);
}
}
if ($character!=32) { $spacestart=0; }
}
}
/**
* Function coverts number of utf char into that character.
* Function taken from: http://sk2.php.net/manual/en/function.utf8-encode.php#49336
*
* @param int $num
* @return utf8char
*/
function code2utf($num)
{
if($num<128)return chr($num);
if($num<2048)return chr(($num>>6)+192).chr(($num&63)+128);
if($num<65536)return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
if($num<2097152)return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128) .chr(($num&63)+128);
return '';
}
?>
</BODY>
</HTML>
// 驗證 Unicode UTF-8 版本 4
// 這個函數參考 http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf 中的表 3.6
// 它也會將過長的位元組標記為錯誤
function is_validUTF8($str)
{
// -1 的值表示目前 UTF-8 中第一個位元組不允許的值
static $trailing_bytes = array (
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
);
$ups = unpack('C*', $str);
if (!($aCnt = count($ups))) return true; // 空字串 *是* 合法的 UTF-8
for ($i = 1; $i <= $aCnt;)
{
if (!($tbytes = $trailing_bytes[($b1 = $ups[$i++])])) continue;
if ($tbytes == -1) return false;
$first = true;
while ($tbytes > 0 && $i <= $aCnt)
{
$cbyte = $ups[$i++];
if (($cbyte & 0xC0) != 0x80) return false;
if ($first)
{
switch ($b1)
{
case 0xE0
if ($cbyte < 0xA0) return false;
break;
case 0xED
if ($cbyte > 0x9F) return false;
break;
case 0xF0
if ($cbyte < 0x90) return false;
break;
case 0xF4
if ($cbyte > 0x8F) return false;
break;
default
break;
}
$first = false;
}
$tbytes--;
}
if ($tbytes) return false; // EOS 時序列不完整
}
return true;
}
如果你還沒猜到:如果 UTF-8 字元在 ISO-8859-1 字碼頁中沒有表示法,則會回傳 ?。你可能會想在這個函數外包裝一個函數,以確保你不會將一堆 ???? 儲存到你的資料庫中。
<?php
/**
* 將 ISO-8859-1 混合變數編碼為 UTF-8 (PHP 4、PHP 5 相容)
* @param mixed $input 一個陣列,關聯或簡單
* @param boolean $encode_keys 可選
* @return mixed ( UTF-8 編碼的 $input)
*/
function utf8_encode_mix($input, $encode_keys=false)
{
if(is_array($input))
{
$result = array();
foreach($input as $k => $v)
{
$key = ($encode_keys)? utf8_encode($k) : $k;
$result[$key] = utf8_encode_mix( $v, $encode_keys);
}
}
else
{
$result = utf8_encode($input);
}
return $result;
}
?>
我建議對每種語言都使用這個替代方案
$new=mb_convert_encoding($s,"UTF-8","auto");
別忘了將所有頁面設定為 "utf-8" 編碼,否則就使用 HTML 實體。
jcn50.
避免使用 preg_match 來偵測是否需要 utf8_encode
<?php
$string = $string_input; // 避免破壞性操作
$string = preg_replace("#[\x09\x0A\x0D\x20-\x7E]#" ,"",$string); // ASCII
$string = preg_replace("#[\xC2-\xDF][\x80-\xBF]#" ,"",$string); // 非過長 2 位元組
$string = preg_replace("#\xE0[\xA0-\xBF][\x80-\xBF]#" ,"",$string); // 排除過長字元
$string = preg_replace("#[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}#","",$string); // 直接 3 位元組
$string = preg_replace("#\xED[\x80-\x9F][\x80-\xBF]#" ,"",$string); // 排除代理對
$string = preg_replace("#\xF0[\x90-\xBF][\x80-\xBF]{2}#","",$string); // 平面 1-3
$string = preg_replace("#[\xF1-\xF3][\x80-\xBF]{3}#" ,"",$string); // 平面 4-15
$string = preg_replace("#\xF4[\x80-\x8F][\x80-\xBF]{2}#","",$string); // 平面 16
$rc = ($string == ""?true:false);
?>
我使用這個函數將泰文字體 (iso-8859-11) 轉換為 UTF-8。就我的情況而言,它可以正常工作。如果你在將字元集 iso-8859-11 轉換為 UTF-8 時遇到問題,請嘗試使用此函數。
function iso8859_11toUTF8($string) {
if ( ! ereg("[\241-\377]", $string) )
return $string;
$iso8859_11 = array(
"\xa1" => "\xe0\xb8\x81",
"\xa2" => "\xe0\xb8\x82",
"\xa3" => "\xe0\xb8\x83",
"\xa4" => "\xe0\xb8\x84",
"\xa5" => "\xe0\xb8\x85",
"\xa6" => "\xe0\xb8\x86",
"\xa7" => "\xe0\xb8\x87",
"\xa8" => "\xe0\xb8\x88",
"\xa9" => "\xe0\xb8\x89",
"\xaa" => "\xe0\xb8\x8a",
"\xab" => "\xe0\xb8\x8b",
"\xac" => "\xe0\xb8\x8c",
"\xad" => "\xe0\xb8\x8d",
"\xae" => "\xe0\xb8\x8e",
"\xaf" => "\xe0\xb8\x8f",
"\xb0" => "\xe0\xb8\x90",
"\xb1" => "\xe0\xb8\x91",
"\xb2" => "\xe0\xb8\x92",
"\xb3" => "\xe0\xb8\x93",
"\xb4" => "\xe0\xb8\x94",
"\xb5" => "\xe0\xb8\x95",
"\xb6" => "\xe0\xb8\x96",
"\xb7" => "\xe0\xb8\x97",
"\xb8" => "\xe0\xb8\x98",
"\xb9" => "\xe0\xb8\x99",
"\xba" => "\xe0\xb8\x9a",
"\xbb" => "\xe0\xb8\x9b",
"\xbc" => "\xe0\xb8\x9c",
"\xbd" => "\xe0\xb8\x9d",
"\xbe" => "\xe0\xb8\x9e",
"\xbf" => "\xe0\xb8\x9f",
"\xc0" => "\xe0\xb8\xa0",
"\xc1" => "\xe0\xb8\xa1",
"\xc2" => "\xe0\xb8\xa2",
"\xc3" => "\xe0\xb8\xa3",
"\xc4" => "\xe0\xb8\xa4",
"\xc5" => "\xe0\xb8\xa5",
"\xc6" => "\xe0\xb8\xa6",
"\xc7" => "\xe0\xb8\xa7",
"\xc8" => "\xe0\xb8\xa8",
"\xc9" => "\xe0\xb8\xa9",
"\xca" => "\xe0\xb8\xaa",
"\xcb" => "\xe0\xb8\xab",
"\xcc" => "\xe0\xb8\xac",
"\xcd" => "\xe0\xb8\xad",
"\xce" => "\xe0\xb8\xae",
"\xcf" => "\xe0\xb8\xaf",
"\xd0" => "\xe0\xb8\xb0",
"\xd1" => "\xe0\xb8\xb1",
"\xd2" => "\xe0\xb8\xb2",
"\xd3" => "\xe0\xb8\xb3",
"\xd4" => "\xe0\xb8\xb4",
"\xd5" => "\xe0\xb8\xb5",
"\xd6" => "\xe0\xb8\xb6",
"\xd7" => "\xe0\xb8\xb7",
"\xd8" => "\xe0\xb8\xb8",
"\xd9" => "\xe0\xb8\xb9",
"\xda" => "\xe0\xb8\xba",
"\xdf" => "\xe0\xb8\xbf",
"\xe0" => "\xe0\xb9\x80",
"\xe1" => "\xe0\xb9\x81",
"\xe2" => "\xe0\xb9\x82",
"\xe3" => "\xe0\xb9\x83",
"\xe4" => "\xe0\xb9\x84",
"\xe5" => "\xe0\xb9\x85",
"\xe6" => "\xe0\xb9\x86",
"\xe7" => "\xe0\xb9\x87",
"\xe8" => "\xe0\xb9\x88",
"\xe9" => "\xe0\xb9\x89",
"\xea" => "\xe0\xb9\x8a",
"\xeb" => "\xe0\xb9\x8b",
"\xec" => "\xe0\xb9\x8c",
"\xed" => "\xe0\xb9\x8d",
"\xee" => "\xe0\xb9\x8e",
"\xef" => "\xe0\xb9\x8f",
"\xf0" => "\xe0\xb9\x90",
"\xf1" => "\xe0\xb9\x91",
"\xf2" => "\xe0\xb9\x92",
"\xf3" => "\xe0\xb9\x93",
"\xf4" => "\xe0\xb9\x94",
"\xf5" => "\xe0\xb9\x95",
"\xf6" => "\xe0\xb9\x96",
"\xf7" => "\xe0\xb9\x97",
"\xf8" => "\xe0\xb9\x98",
"\xf9" => "\xe0\xb9\x99",
"\xfa" => "\xe0\xb9\x9a",
"\xfb" => "\xe0\xb9\x9b"
);
$string=strtr($string,$iso8859_11);
return $string;
}
Suttichai Mesaard-www.ceforce.com
/*
目前為止看到的所有函式都不完整或消耗資源。這裡有兩個函式 -- 整數到 UTF 序列 (i3u) 和 UTF 序列到整數 (u3i)。以下是檢查範圍邊界行為的程式碼片段。
或許有一天它們會被硬編碼到 PHP 中...
*/
function i3u($i) { // 從整數返回 UCS-16 或 UCS-32 到 UTF-8
$i=(int)$i; // 整數嗎?
if ($i<0) return false; // 正數嗎?
if ($i<=0x7f) return chr($i); // 範圍 0
if (($i & 0x7fffffff) <> $i) return '?'; // 31 位元嗎?
if ($i<=0x7ff) return chr(0xc0 | ($i >> 6)) . chr(0x80 | ($i & 0x3f));
if ($i<=0xffff) return chr(0xe0 | ($i >> 12)) . chr(0x80 | ($i >> 6) & 0x3f)
. chr(0x80 | $i & 0x3f);
if ($i<=0x1fffff) return chr(0xf0 | ($i >> 18)) . chr(0x80 | ($i >> 12) & 0x3f)
. chr(0x80 | ($i >> 6) & 0x3f) . chr(0x80 | $i & 0x3f);
if ($i<=0x3ffffff) return chr(0xf8 | ($i >> 24)) . chr(0x80 | ($i >> 18) & 0x3f)
. chr(0x80 | ($i >> 12) & 0x3f) . chr(0x80 | ($i >> 6) & 0x3f) . chr(0x80 | $i & 0x3f);
return chr(0xfc | ($i >> 30)) . chr(0x80 | ($i >> 24) & 0x3f) . chr(0x80 | ($i >> 18) & 0x3f)
. chr(0x80 | ($i >> 12) & 0x3f) . chr(0x80 | ($i >> 6) & 0x3f) . chr(0x80 | $i & 0x3f);
}
function u3i($s,$strict=1) { // 在有效的 UTF-8 序列上返回整數,在空字串上返回 NULL,否則返回 FALSE
// 非嚴格:僅取得資料位元,無論是否存在;嚴格:長度和位元檢查
if ($s=='') return NULL;
$l=strlen($s); $o=ord($s{0});
if ($o <= 0x7f && $l==1) return $o;
if ($l>6 && $strict) return false;
if ($strict) for ($i=1;$i<$l;$i++) if (ord($s{$i}) > 0xbf || ord($s{$i})< 0x80) return false;
if ($o < 0xc2) return false; // 即使 strict=0 也不行
if ($o <= 0xdf && ($l=2 && $strict)) return (($o & 0x1f) << 6 | (ord($s{1}) & 0x3f));
if ($o <= 0xef && ($l=3 && $strict)) return (($o & 0x0f) << 12 | (ord($s{1}) & 0x3f) << 6
| (ord($s{2}) & 0x3f));
if ($o <= 0xf7 && ($l=4 && $strict)) return (($o & 0x07) << 18 | (ord($s{1}) & 0x3f) << 12
| (ord($s{2}) & 0x3f) << 6 | (ord($s{3}) & 0x3f));
if ($o <= 0xfb && ($l=5 && $strict)) return (($o & 0x03) << 24 | (ord($s{1}) & 0x3f) << 18
| (ord($s{2}) & 0x3f) << 12 | (ord($s{3}) & 0x3f) << 6 | (ord($s{4}) & 0x3f));
if ($o <= 0xfd && ($l=6 && $strict)) return (($o & 0x01) << 30 | (ord($s{1}) & 0x3f) << 24
| (ord($s{2}) & 0x3f) << 18 | (ord($s{3}) & 0x3f) << 12
| (ord($s{4}) & 0x3f) << 6 | (ord($s{5}) & 0x3f));
return false;
}
// 邊界行為檢查
$do=array(0x7f,0x7ff,0xffff,0x1fffff,0x3ffffff,0x7fffffff);
foreach ($do as $ii) for ($i=$ii;$i<=$ii+1; $i++) {
$o=i3u($i);
for ($j=0;$j<strlen($o);$j++) print "O[$j]=" . sprintf('%08b',ord($o{$j})) . ", ";
print "c=$i, o=[$o].\n";
print "Back: [$o] => [" . u3i($o) . "]\n";
}
/**
* 將陣列的所有值轉換為 utf8_encode
* @author Marcelo Ratton
* @version 1.0
*
* @param array $arr 要編碼值的陣列
* @param bool $keys 是否將鍵轉換為 UTF8
* @return array 相同陣列,但所有值都已編碼為 UTF8
*/
function arrayEncodeToUTF8(array $arr, bool $keys= false) : array {
$ret= [];
foreach ($arr as $k=>$v) {
if (is_array($v)) {
$ret[$k]= arrayEncodeToUTF8($v);
} else {
if ($keys) {
$k= utf8_encode((string)$k);
}
$ret[$k]= utf8_encode((string)$v);
}
}
return $ret;
}
以下函式會以 utf-8 編碼 Unicode 實體 &#nnn(nn);,其中 n={0..9}
/**
* 接受 Unicode 實體字串並將其轉換為 utf-8 編碼字串
* 每個 Unicode 實體都具有 &#nnn(nn); 的形式,其中 n={0..9},並且可以由支援 utf-8 的
* 瀏覽器顯示。ASCII 不會被修改。
* @param $source Unicode 實體字串 [STRING]
* @return utf-8 編碼字串 [STRING]
* @access public
*/
function utf8Encode ($source) {
$utf8Str = '';
$entityArray = explode ("&#", $source);
$size = count ($entityArray);
for ($i = 0; $i < $size; $i++) {
$subStr = $entityArray[$i];
$nonEntity = strstr ($subStr, ';');
if ($nonEntity !== false) {
$unicode = intval (substr ($subStr, 0, (strpos ($subStr, ';') + 1)));
// 判斷表示此 Unicode 字元需要多少個字元
if ($unicode < 128) {
$utf8Substring = chr ($unicode);
}
else if ($unicode >= 128 && $unicode < 2048) {
$binVal = str_pad (decbin ($unicode), 11, "0", STR_PAD_LEFT);
$binPart1 = substr ($binVal, 0, 5);
$binPart2 = substr ($binVal, 5);
$char1 = chr (192 + bindec ($binPart1));
$char2 = chr (128 + bindec ($binPart2));
$utf8Substring = $char1 . $char2;
}
else if ($unicode >= 2048 && $unicode < 65536) {
$binVal = str_pad (decbin ($unicode), 16, "0", STR_PAD_LEFT);
$binPart1 = substr ($binVal, 0, 4);
$binPart2 = substr ($binVal, 4, 6);
$binPart3 = substr ($binVal, 10);
$char1 = chr (224 + bindec ($binPart1));
$char2 = chr (128 + bindec ($binPart2));
$char3 = chr (128 + bindec ($binPart3));
$utf8Substring = $char1 . $char2 . $char3;
}
else {
$binVal = str_pad (decbin ($unicode), 21, "0", STR_PAD_LEFT);
$binPart1 = substr ($binVal, 0, 3);
$binPart2 = substr ($binVal, 3, 6);
$binPart3 = substr ($binVal, 9, 6);
$binPart4 = substr ($binVal, 15);
$char1 = chr (240 + bindec ($binPart1));
$char2 = chr (128 + bindec ($binPart2));
$char3 = chr (128 + bindec ($binPart3));
$char4 = chr (128 + bindec ($binPart4));
$utf8Substring = $char1 . $char2 . $char3 . $char4;
}
if (strlen ($nonEntity) > 1)
$nonEntity = substr ($nonEntity, 1); // 去掉第一個字元 (';')
else
$nonEntity = '';
$utf8Str .= $utf8Substring . $nonEntity;
}
else {
$utf8Str .= $subStr;
}
}
return $utf8Str;
}
Ronen.
關於先前將 GB2312 程式碼轉換為 Unicode 程式碼的文章,其中顯示了以下函式
<?
// 由 sadly (www.phpx.com) 撰寫
function gb2unicode($gb)
{
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,9,4);
$utf="";
while($gb)
{
if (ord(substr($gb,0,1))>127)
{
$this=substr($gb,0,2);
$gb=substr($gb,2,strlen($gb));
$utf.="&#x".$codetable[hexdec(bin2hex($this))-0x8080].";";
}
else
{
$gb=substr($gb,1,strlen($gb));
$utf.=substr($gb,0,1);
}
}
return $utf;
}
?>
我發現程式碼中需要做一些小變更,才能正確處理嵌在 gb2312 文字中間的拉丁字元,例如文字包含 URL 或電子郵件地址時。只需反轉以上處理 ord 值 !>127 的陳述式中的兩行即可。
變更為
$gb=substr($gb,1,strlen($gb));
$utf.=substr($gb,0,1);
改為
$utf.=substr($gb,0,1);
$gb=substr($gb,1,strlen($gb));
在原始函式中,第一個拉丁字元會被捨棄,並且它不會轉換拉丁文字之後的第一個非拉丁字元(所有內容都向右移動了一個字元)。反轉這兩行可以讓它在所有我嘗試過的範例中正確運作。
此外,此函式所需的 gb2312.txt 檔案的來源已變更。您可以在幾個地方找到它
http://tcl.apache.org/sources/tcl/tools/encoding/gb2312.txt
ftp://ftp.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/GB/GB2312.TXT
我經常需要轉換傳送給我的多語言文字,以用於網站和其他應用程式中,轉換為 UTF8 編碼,以便我可以將其插入原始程式碼和資料庫中。
我建立了一個小型網頁,其字元集設定為 UTF8,然後將其設定為我可以從原始文件(例如 Word 或 Excel)貼上,並讓該頁面傳回 UTF8 編碼版本。
當然,瀏覽器會將 Unicode 轉換為 UTF8 作為提交的一部分(我使用 IE5 或更高版本來執行此操作),然後您在 PHP 中要做的就是編碼 UTF8,以便瀏覽器以其原始形式顯示它。
它有點笨重,但我只是將所有字元轉換為 HTML 編號實體(蠻力再次做到)。
我使用它來編碼從希伯來文到日文的所有內容,沒有問題。
<?
header("Content-Type: text/plain; charset=utf-8");
$code = (get_magic_quotes_gpc())?stripslashes($GLOBALS[code]):$GLOBALS[code];
?>
<html>
<head>
<title>UTF8 編碼器頁面</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form method=post action="?seed=<?=time()?>">
原始 Unicode<br />
<textarea name="code" cols="80" rows="10"><?=$code?></textarea><br />
編碼的 UTF8<br />
<textarea name="encd" cols="80" rows="10"><?
for ($i = 0; $i < strlen($code); $i++) {
echo '&#'.ord(substr($code,$i,1));
}
?></textarea><br />
<input type="submit" value="encode">
</form>
</body>
</html>
以下的 Perl 正規表示式會測試一個字串是否為格式良好的 Unicode UTF-8(為了避免過長的行,我在每個 | 符號後斷開。使用前請將它們合併為單一行,不要有空格。)
^([\x00-\x7f]|
[\xc2-\xdf][\x80-\xbf]|
\xe0[\xa0-\xbf][\x80-\xbf]|
[\xe1-\xec][\x80-\xbf]{2}|
\xed[\x80-\x9f][\x80-\xbf]|
[\xee-\xef][\x80-\xbf]{2}|
f0[\x90-\xbf][\x80-\xbf]{2}|
[\xf1-\xf3][\x80-\xbf]{3}|
\xf4[\x80-\x8f][\x80-\xbf]{2})*$
注意:這嚴格遵循 Unicode 標準 4.0,如第 3.9 章,表 3-6,「格式良好的 UTF-8 位元組序列」中所述 ( http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G31703 )。
ISO-10646 是 Unicode 的超集,它使用 UTF-8(在那裡稱為 "UCS",請參閱 http://www.unicode.org/faq/utf_bom.html#1 )的一個較寬鬆的變體,它支援將 31 位元的空間編碼為最多六個位元組,而不是 Unicode 的最多四個位元組的 21 位元。要檢查 ISO-10646 UTF-8,請使用以下的 Perl 正規表示式(再次,已斷開,請參閱上方):
^([\x00-\x7f]|
[\xc0-\xdf][\x80-\xbf]|
[\xe0-\xef][\x80-\xbf]{2}|
[\xf0-\xf7][\x80-\xbf]{3}|
[\xf8-\xfb][\x80-\xbf]{4}|
[\xfc-\xfd][\x80-\xbf]{5})*$
以下函數可與上述的表示式一起使用,進行快速 UTF-8 測試,例如,如果從 <form accept-charset="utf-8,iso-8859-1" method=..> 提交,用來區分 ISO-8859-1 資料和 UTF-8 資料。
function is_utf8($string) {
return (preg_match('/[在此處插入正規表示式]/', $string) === 1);
}