原理很簡單,因為gb2312/gbk是中文兩字節,這兩個字節是有取值范圍的,而utf-8中漢字是三字節,同樣每個字節也有取值范圍。而英文不 管在何種編碼情況下,都是小於128,只占用一個字節(全角除外)。
如果是文件形式的編碼檢查,還可以直接check utf-8的BOM信息。話不多說,直接上函數,這個函數是用來對字符串進行檢查和轉碼的。
<?php function safeEncoding($string,$outEncoding ='UTF-8') { $encoding = "UTF-8"; for($i=0;$i<strlen($string);$i++) { if(ord($string{$i})<128) continue; if((ord($string{$i})&224)==224) { //第一個字節判斷通過 $char = $string{++$i}; if((ord($char)&128)==128) { //第二個字節判斷通過 $char = $string{++$i}; if((ord($char)&128)==128) { $encoding = "UTF-8"; break; } } } if((ord($string{$i})&192)==192) { //第一個字節判斷通過 $char = $string{++$i}; if((ord($char)&128)==128) { // 第二個字節判斷通過 $encoding = "GB2312"; break; } } } if(strtoupper($encoding) == strtoupper($outEncoding)) return $string; else return iconv($encoding,$outEncoding,$string); } ?>
字節順序記號(英:byte-order mark,BOM)是位於碼點 U+FEFF 的統一碼字符("零寬度無斷空白")。當以 UTF-16 或 UTF-32 來將UCS/統一碼字符所組成的字串編碼時,這個字符被用來標示其字節序。它常被用來當做標示文件是以 UTF-8 、 UTF-16 或 UTF-32 編碼的記號。
在大部分的字符編碼中,字節順序記號是一個不太可能出現在其它文件的樣式(它通常看起來像是一個混淆的控制碼的序列)。如果字節順序記號被誤解成統一碼文件中真正的字符時,那麼它將不可視,因為它是零寬度無斷空白。在 Unicode3.2 中, U+FEFF 用於非字節順序記號的用途已被捨棄(取而代之的是,使用 U+2060 來表示這種用途),以容許 U+FEFF 僅被地用於字節順序記號的語意。
在 UTF-16 中,字節順序記號被放置為檔案或字符串流的第一個字符,以標示在此檔案或字符串流中,以所有十六位元為單位的字碼的尾序(字節順序)。
而統一碼中,值為U+FFFE 的碼位被保證將不會被指定成一個統一碼字符。這意味著 0xFF 、 0xFE 將只能被解釋成小尾序中的U+FEFF(因為不可能是大尾序中的 U+FFFE )。
UTF-8 則沒有字節順序的議題。UTF-8編碼過的字節順序記號則被用來標示它是 UTF-8 的文件。它只用來標示一個 UTF-8 的檔案,而不用來說明字節順序。[1] 許多 視窗 程式(包含記事本)會添加字節順序記號到 UTF-8 檔案。然而,在 類Unix系統 系統(大量使用 en:text file ,用於 檔案格式 ,用於行程間通訊)中,這種作法則不被建議采用。因為它會妨礙到如解譯器腳本開頭的 en:Shebang 等的一些重要的碼的正確處理。它亦會影響到無法識別它的編程語言。如 gcc 會報告源碼檔開頭有無法識別的字符。而在 PHP 中,如果沒有啟用輸出緩沖(output buffering),它會使得頁面內容開始被送往浏覽器(即:用戶標頭檔已被送出),這使 PHP 腳本無法指定用戶標頭檔(HTTP Header)。字節順序記號在 UTF-8 中被表示為序列 EF BB BF,對大部分未准備好處理 UTF-8 的 文本編輯器 及 網頁浏覽器 而言,在 ISO-8859-1 的環境中則會顯示 ??? 。
雖然字節順序記號亦可以用於 UTF-32 ,但這個編碼很少用於傳輸,其規則如同 UTF-16 。對於已於IANA注冊的字符集 UTF-16BE、UTF-16LE 、 UTF-32BE 和 UTF-32LE 等來說,不可使用字節順序記號。文檔開頭的 U+FEFF 會被解釋成一個(已捨棄的)"零寬度無斷空白",因為這些字符集的名字已決定了其字節順序。對於已注冊字符集 UTF-16 和 UTF-32 來說,一個開頭的 U+FEFF 則用來表示字節順序。