我刚开始涉猎php,但是我需要一些帮助来搞清楚如何处理UTF-8编码的字符串。
我正在使用Ubuntu 11.10 x86,PHP版本为5.3.6-13ubuntu3.2。我有一个UTF-8编码的文件(vim :set encoding
确认了这一点),然后我使用以下方式读取它:
$file = fopen("file.txt", "r");
while(!feof($file)){
$line = fgets($file);
//...
}
fclose($file);
- 使用
mb_detect_encoding($line)
报告UTF-8
- 如果我执行
echo $line
,则可以在浏览器中正确查看该行(无损坏字符)。- 所以我猜测浏览器和Apache都没有问题。尽管我搜索了我的Apache配置AddDefaultCharset,并尝试添加字符编码的http元标签(以防万一)
当我尝试使用$arr = mb_split(';',$line)
拆分字符串时,生成的数组的字段包含乱码的utf-8字符(mb_detect_encoding($arr[0])
也报告utf-8)。
因此,echo $arr[0]
将导致出现以下内容:ΑΘΗÎÎ
。
我尝试设置mb_detect_order('utf-8')
,mb_internal_encoding('utf-8')
,但是没有任何变化。我还尝试手动检测utf-8,使用这个w3 perl正则表达式,因为我在某个地方读到mb_detect_encoding有时可能会失败(误传?),但结果也是一样的。
所以我的问题是如何正确地拆分字符串?走mb_
的路线是错误的吗?我漏掉了什么?
谢谢你的帮助!
更新:我正在添加示例字符串和base64等效项(感谢@chris'的建议)
1. original string: "ΑΘΗΝΑ;ΑΙΓΑΛΕΩ;12242;37.99452;23.6889"
2. base64 encoded: "zpHOmM6Xzp3OkTvOkc6ZzpPOkc6bzpXOqTsxMjI0MjszNy45OTQ1MjsyMy42ODg5"
3. first part (the equivalent of "ΑΘΗΝΑ") base64 encoded before splitting: "zpHOmM6Xzp3OkQ=="
4. first part ($arr[0] after splitting): "ΑΘΗÎΑ"
5. first part after splitting base64 encoded: "77u/zpHOmM6Xzp3OkQ=="
好的,这样做后,第3和第5之间似乎存在一个77u/
的差异,根据这篇文章,这是一个UTF-8 BOM标记。那么我该如何避免它呢?
更新2:今天早上我精神焕发,记住了你们的建议,再次尝试了一下。看起来$line=fgets($file)
可以正确读取第一行(没有损坏的字符),但对于每个后续行都失败了。所以我将第一行和第二行进行了base64_encoded
,然后只有第一行的base64字符串出现了77u/
bom。然后我在vim中打开了有问题的文件,并输入了:set nobomb
:w
以不带bom的方式保存文件。再次启动php时,发现第一行现在也被损坏了。基于@hakre的remove_utf8_bom
,我添加了它的补充函数。
function add_utf8_bom($str){
$bom= "\xEF\xBB\xBF";
return substr($str,0,3)===$bom?$str:$bom.$str;
}
神奇地,每一行现在都被正确读取了。
我并不太喜欢这个解决方案,因为它看起来非常非常hackish(我不敢相信整个框架/语言都没有提供处理nobombed字符串的方法)。那么你知道其他替代方法吗?否则我将继续上述方法。
感谢@chris、@hakre和@jacob的时间!
更新3(解决方案):结果证明这是一个浏览器问题:添加header('Content-type: text/html; charset=UTF-8')
以及类似于<meta http-equiv="Content-type" value="text/html; charset=UTF-8" />
的meta标签是不够的。它还必须正确地包含在<html><body>
部分中,否则浏览器无法正确理解编码。感谢@jake的建议。
故事寓意:在尝试为浏览器编写代码之前,我应该更多地学习html。感谢大家的帮助和耐心。
echo $line
之前,写入类似于echo '<!DOCTYPE html><html><head><meta charset=utf-8><title>Test Page</title></head><body>';
的内容。 - Jakob Egger