說(shuō)明
在使用 PHP 的時(shí)候,可能會(huì)遇到編解碼的錯(cuò)誤。這里面的編解碼包括 BASE64、json_encode、json_decode 等。
下面是使用 YII2 框架,一個(gè)請(qǐng)求在返回?cái)?shù)據(jù)的數(shù)據(jù)時(shí)候,出現(xiàn)的錯(cuò)誤:
Malformed UTF-8 characters, possibly incorrectly encoded.
問(wèn)題和解決方案
出現(xiàn)上面的問(wèn)題,可能有下面幾種情況:
字符集不統(tǒng)一
編解碼前后使用的字符集不一致,導(dǎo)致編碼成一種字符集,解碼的時(shí)候是另一種字符集。要檢查編解碼前后的字符集是否一致。
可以使用下面的一些函數(shù)進(jìn)行檢查。
# 設(shè)置內(nèi)部字符編碼為 UTF-8
mb_internal_encoding("UTF-8");
# 顯示當(dāng)前的內(nèi)部字符編碼
echo mb_internal_encoding();
# 檢測(cè) HTTP 輸入字符編碼
mb_http_input()
# 設(shè)置/獲取 字符編碼的檢測(cè)順序
mb_detect_order()
# 設(shè)置/獲取 HTTP 輸出字符編碼
mb_http_output()
# 設(shè)置/獲取多字節(jié)正則表達(dá)式的字符編碼
mb_regex_encoding()
全局設(shè)置指定的字符集
方法1:代碼中設(shè)置成 UTF-8 字符集:
mb_internal_encoding("UTF-8")
方法2:在 php.ini 中設(shè)置
mbstring.internal_encoding = UTF-8
字符集轉(zhuǎn)換
將指定字符串從 encoding1 字符集。
mb_convert_encoding($str, $encoding1, $encoding2);
參數(shù)說(shuō)明encoding1:目標(biāo)編碼,如utf-8,gbk,大小寫均可;
$encoding2:原編碼,如utf-8,gbk,大小寫均可。
案例一
$str='你好,世界';
// 編碼轉(zhuǎn)換為utf-8
echo mb_convert_encoding($str, "UTF-8");
案例二
$str='你好,世界';
// 已知原編碼為GBK,轉(zhuǎn)換為utf-8
echo mb_convert_encoding($str, "UTF-8", "GBK");
案例三
$str='你好,世界';
// 把 GBK,GB2312,BIG5 這幾種編碼轉(zhuǎn)成 UTF-8 編碼。
$content = mb_convert_encoding($str, 'UTF-8', 'GBK,GB2312,BIG5');
案例四
$str='你好,世界';
// 未知原編碼,通過(guò)auto自動(dòng)檢測(cè)后,轉(zhuǎn)換編碼為utf-8
echo mb_convert_encoding($str, "UTF-8", "auto");
不可編碼的數(shù)據(jù)
在使用 json 進(jìn)行編碼的時(shí)候,編碼的數(shù)據(jù)可能經(jīng)過(guò) base64 進(jìn)行解碼,但是原數(shù)據(jù)可能不是 base64 編碼的,因此會(huì)導(dǎo)致 base64 解碼錯(cuò)誤,然后再使用 json 進(jìn)行 json_encode 等編碼時(shí),出現(xiàn)上面的錯(cuò)誤。
該問(wèn)題需要檢查進(jìn)入 json_encode 的數(shù)據(jù),是否是正常數(shù)據(jù),如果操作的數(shù)據(jù)不是正常字符數(shù)據(jù),json_encode 可能會(huì)返回空,也可能會(huì)返回 true、false 之類的數(shù)據(jù),也可能報(bào)錯(cuò)。
在 YII2 中,如果返回的是 JSON 格式的數(shù)據(jù),框架在執(zhí)行 Respnose 方法的時(shí)候,會(huì)調(diào)用
BaseJson.php 中的 encode 方法:
BaseJson::encode($str);
如果 $str 數(shù)據(jù)不是正常數(shù)據(jù),此處也會(huì)報(bào)上面的錯(cuò)誤。
所以要檢查好 json_encode 的數(shù)據(jù)是否是正常數(shù)據(jù)。