背景:
- 编码问题在Python同学眼中应该是老生常谈的,本文谈下PHP中常见的编码相关检测方法及局限
- 数据在写入时决定了编码形式,而由于历史变更可能存在历史数据中写入编码不同
- 编码检测的目的:检测数据的编码形式,正确解码及界面展示
PHP中不同编码检测方法
mb_detect_encoding检测
mb_detect_encoding
函数中$encoding_list
参数中编码顺序不同,会影响最终检测的结果。
1 | // 用法: |
自定义实现的is_utf8()和is_gbk()方法
这个来源是流传较广的一种写法
1 | public static function is_utf8($str) |
iconv同编码转换后判等方式
- 通过
iconv
判断转换前后的内容是否一致,作为编码检测的依据 - 优劣
- 必须指定检测范围
- 在明确范围的情况下,检测准确性最佳
1 | function detectEncoding ($str) { |
实例验证
先看个正常的例子:
- 小知识:GBK 和 CP936可以认为是同一种编码的不同叫法,CP936是GBK的实时实现。
1 | $str = '天下相思'; |
- 再一个极端的例子,不论哪种方式检测,都无法做到100%正确?
- 此时严重依赖detectList中指定的待检测编码的顺序,也就是说可能误判为utf8,而此时如果输出则会乱码(实际并非utf8编码)
1 | $str = '鸶姬'; // 本地utf8编码 |
结论&注意事项
- 编码检测的准确性,验证依赖
detectList
待检测编码的顺序,应将范围小的在前,减少误判的概率(但无法避免) - 同时存在不同编码下字符,编码值保持相同,所以编码检测结果是首个包含此字符的编码,如英文词汇的gbk/utf8编码结果相同
- 一种编码检测及转换为utf8的可行方案
1 | // 注意,这里仅支持gbk/utf8的编码检测,且数据源多数为gbk编码 |