沒想到規則意外的簡單,因為我不須知道太詳細的細節,只需知道幾個重點:
- 只要是0開頭的byte就表示是ascii編碼,也就是0xxxxxxx後面的七碼x相容於傳統ascii編碼
- 非ascii編碼,一律以1開頭再接0,並且最少兩個1
- 1的數量指出這個字是由幾個byte所組成,如1110xxxxx表示這個字要3個byte
- 其後每個子byte都為10開頭
- 最多每個字4個byte
- 依照規格,只要有非0、非110、非1110、非11110開頭的byte,就是非utf-8
- 110開頭的byte,需檢查是否有下一個byte,或底下一個byte是否為10開頭
- 1110開頭的byte,需檢查是否有下兩個byte,或底下兩個byte是否皆為10開頭
- 11110開頭的byte,需檢查是否有下三個byte,或底下三個byte是否皆為10開頭
- 全部byte跑完之後的指標是否等於檔案長度
底下就是程式碼了:
- /// <summary>
- /// 檢查是否符合utf-8編碼的核心程式
- /// </summary>
- /// <param name="bytes">文字原始byte陣列</param>
- /// <returns></returns>
- private static bool _IsUtf8(byte[] bytes) {
- int i = 0;
- int size = bytes.Length;
- //跑每一個byte,需要每個byte都符合utf-8編碼規則才算是utf-8編碼
- while (i < size) {
- int step = 0;
- if ((bytes[i] & 0x80) == 0x00) {
- //utf-8的ascii字元,為0開頭,OK跑下一個位元
- step = 1;
- }
- else if ((bytes[i] & 0xE0) == 0xC0) {
- /*
- 110xxxxx
- & 11100000 (0xE0)
- ----------
- 11000000 (0xC0)
- */
- //utf-8使用2bytes編碼格式為 110xxxxx 10xxxxxx
- //如果是110xxxxx開頭,要判斷下個位元是否是10開頭
- //如果下一個已經沒有資料了,表示這不是utf-8編碼
- if (i + 1 >= size) { return false; }
- //如果下個位元不是10開頭,也表示這不是utf-8編碼
- if ((bytes[i + 1] & 0xC0) != 0x80) { return false; }
- //繼續跑下2個
- step = 2;
- }
- else if ((bytes[i] & 0xF0) == 0xE0) {
- /*
- 1110xxxx
- & 11110000 (0xF0)
- ----------
- 11100000 (0xE0)
- */
- //utf-8使用3bytes編碼格式為 1110xxxx 10xxxxxx 10xxxxxx
- //所以如果是1110xxxx開頭,要判斷下兩個byte是否都是10開頭
- //如果下兩個已經沒有資料了,表示不是utf-8編碼
- if (i + 2 >= size) { return false; }
- //如果下兩個位元不是10開頭,也不是utf-8編碼
- if ((bytes[i + 1] & 0xC0) != 0x80) { return false; }
- if ((bytes[i + 2] & 0xC0) != 0x80) { return false; }
- //繼續跑下3個
- step = 3;
- }
- else if ((bytes[i] & 0xF8) == 0xF0) {
- /*
- 11110xxx
- & 11111000 (0xF8)
- ----------
- 11110000 (0xF0)
- */
- //utf-8使用4bytes編碼格式為 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- //所以如果是11110xxx開頭,要判斷下3個byte是否都是10開頭
- //如果下3個已經沒有資料了,表示不是utf-8編碼
- if (i + 3 >= size) { return false; }
- //如果下3個位元不是10開頭,也不是utf-8編碼
- if ((bytes[i + 1] & 0xC0) != 0x80) { return false; }
- if ((bytes[i + 2] & 0xC0) != 0x80) { return false; }
- if ((bytes[i + 3] & 0xC0) != 0x80) { return false; }
- //繼續跑下4個
- step = 4;
- }
- else {
- //如果都不是當然就不是utf-8了
- return false;
- }
- i += step;
- }
- if (i == size) { return true; }
- return false;
- }
參考資料:
沒有留言:
張貼留言