2014-04-01 21 views
3

我解析了一些UTF-8文本,但只對ASCII範圍內的字符感興趣,即我可以跳過多字節序列。獲取多字節UTF-8序列的長度

我可以很容易地檢測到一個序列的開始,因爲符號位已設置,所以char值是< 0.但是,如何判斷序列中有多少個字節,以便我可以跳過?

我不需要執行任何驗證,即我可以假設輸入是有效的UTF-8。

+0

請記住,'char'可以實現爲有符號或無符號,具體取決於您的編譯器。如果char'ch'設置了高位,則可能意味着'ch <0'或者它可能意味着'ch> = 128'。 –

回答

5

只刪除所有無效的字節,不要試圖變得可愛並且理解字節> 127。只要你在ascii範圍內沒有任何具有基本字符的組合序列,就可以工作。對於那些你需要自己解釋代碼點的人。

+0

這不是一個好主意。在這種情況下,您可能包含屬於UTF-8序列的字符 – nothrow

+1

@Yossarian:請舉個例子。 UTF-8明確地使你的情況不可能AFAIK。 – Deduplicator

+1

@Yossarian由多於1個字節(2,3,4)組成的所有UTF-8序列由只有MSBit集的字節組成。 – chux

4

雖然Deduplicator的答案是比較合適的跳過多字節序列,如果有需要得到每個這樣的字符長度的具體目的,第一個字節傳遞給該函數:

int getUTF8SequenceLength (unsigned char firstPoint) { 
    firstPoint >>= 4; 
    firstPoint &= 7; 
    if (firstPoint == 4) return 2; 
    return firstPoint - 3; 
} 

這返回的序列總長度,包括第一個字節。爲了清楚起見,我在這裏使用了一個無符號的char值作爲firstPoint參數,但是請注意,如果該參數是一個有符號的char,則該函數將以完全相同的方式工作。

爲了解釋:

  • UTF-8使用比特5,圖6和7中的序列的第一個字節,以指示剩餘長度。如果全部三個都已設置,則序列爲3個附加字節。如果只設置了從左邊(第7位)開始的這些中的第一個,則序列爲1個附加字節。如果從左側開始的前兩個被設置,則該序列是2個附加字節。因此,我們要考察這三個位(這裏的值只是一個例子):

    11110111 
        ^^^ 
    
  • 值下移4然後AND'd與7.這樣,只有第一,第二,和作爲唯一可能的設置,從右邊的的第3位。這些位的值分別是1,2和4。

    00000111 
        ^^^ 
    
  • 如果現在的值是4,我們只知道從左邊(我們正在考慮三)設置,並且可以返回2.

  • 在此之後的第一位,該值或者7,表示所有三位都被設置,所以序列總共是4個字節,或者6,這意味着從左邊開始的前兩個被設置,因此該序列總共是3個字節。

這涵蓋了用UTF-8表示的有效Unicode字符的範圍。