由編碼識別遇到有關問題,思考utf8編碼Regex(php版本)

來源:互聯網
上載者:User
由編碼識別遇到問題,思考utf8編碼Regex(php版本)

?

  • 起因:

最近遇到一件事情,一個介面能夠接收傳入編碼可能是utf-8,gbk 兩種。 做過編碼方面轉換的同學應該知道的,是什麼編碼不會在字串裡面有什麼標記位的。不過utf-8編碼有特殊性,因此可以通過Regex來檢查。只要發現是utf-8編碼。就轉換,不是utf-8就當gbk處理。 編碼一些常見問題可以查看:由web程式出現亂碼開始挖掘(Bom頭、字元集與亂碼)

  • 行動:

知道這個原理,馬上領任務,開始工作。 想到php版本有個mbstring模組可以進行編碼檢測轉換:

php//當前編碼是gbk$str="中國";$aStrList=array($str,iconv('gbk','utf-8',$str));foreach ($aStrList as $v){echo mb_convert_encoding($v,'gbk','utf-8,gbk'),"\r\n";}
?
運行結果:
 
?
兩個不同編碼的“中國”,用一個函數mb_convert_encoding就可以自動轉換成gbk編碼。首頁,嘗試用utf-8解碼,如果出現問題,就會用gbk轉碼。看來問題解決了,哈哈,可以交差了……
?
  1. 問題:
發布後,平靜了幾天,突然接到反饋:有中文:”袁小”解碼出錯。⊙﹏⊙b汗 …… ,想……(難道php內建檢測模組有問題,或是我哪裡欠缺……)
 
⊙﹏⊙b汗……  看來果然有問題,查詢手冊:mbstring 模組編碼檢查,只是識別字串部分編碼,發現與某個字元集匹配上,就認為它屬於那種編碼。 這不屬於它的bug,因為字串本身沒有編碼資訊標識,沒有那個語言能夠完全檢測通過。 
?
  1. 問題:
能不能自己寫一個檢查Regex看下到底怎麼樣呢?要寫Regex,首先須瞭解utf8編碼規範,查看:http://zh.wikipedia.org/zh/UTF-8?

目前編碼集合只有這樣6個維度:php得到維度代碼

php//得到utf8字編碼各個維度範圍 echo base_convert('1111111',2,16),"\r\n";//維度1echo base_convert('10000000',2,16),base_convert('10111111',2,16),"\r\n";echo base_convert('11000000',2,16),base_convert('11011111',2,16),"\r\n";//維度2echo base_convert('11100000',2,16),base_convert('11101111',2,16),"\r\n";//維度3echo base_convert('11110000',2,16),base_convert('11110111',2,16),"\r\n";//維度4echo base_convert('11111000',2,16),base_convert('11111011',2,16),"\r\n";//維度5echo base_convert('11111100',2,16),base_convert('11111101',2,16),"\r\n";//維度6

運行結果:

  1. 通過上面6個維度得到得到對應的Regex:

[\x01-\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}

以上分別是各個維度範圍

php//當前編碼是gbk$str="袁";echo urlencode($str);echo is_utf8($str);function is_utf8($str){///utf8編碼正則檢測函數///copyright qq:8292669  http://www.cnblogs.com/chengmo$re='/^([\x01-\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})+$/';return preg_match($re,$str);}
上面執行結果返回為1,然後”袁“本身應該是gbk編碼。看來上面函數還是不能徹底檢查utf8編碼。分析原因,從上面正則可以看到,utf8的6個維度對應位元組長度從1-6位元組。 而gbk是1-2個位元組。因此他們之間會在1-2個位元組長度地方檢查出現重合。1個位元組的時候gbk與utf8的 編碼與字元對應關係都一樣,但是2個位元組時候,對應編碼與字元各不相同。
?
通過查詢gbk編碼錶:http://www.knowsky.com/resource/gb2312tbl.htm 進一步確認,範圍會在:
[c0-df][a0-bf]  之內漢字都會有問題了。 如果純這個範圍的漢字組合為字串就會出現判斷不了情況。如果它與其它範圍字元組合都可以正確的判斷出來。
?

GBK與UTF8字元集重疊對應的字元是:(gbk編碼錶)

?

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.