2011-05-18 84 views

回答

10

UTF-8就是爲此而設計的。

def split_utf8(s, n): 
    """Split UTF-8 s into chunks of maximum length n.""" 
    while len(s) > n: 
     k = n 
     while (ord(s[k]) & 0xc0) == 0x80: 
      k -= 1 
     yield s[:k] 
     s = s[k:] 
    yield s 

未經測試。但是你找到了一個分裂的地方,然後回溯到一個角色的開始。

但是,如果用戶可能想要查看單個塊,則可能需要在字形羣集邊界上進行拆分。這是非常複雜的,但不是棘手的。例如,在"é"中,您的可能不想將"e""´"分開。或者你可能不在乎,只要他們最終再次陷入困境。

+0

我測試了這個,它似乎工作。雖然最終用戶會看到這個塊,但我覺得這個解決方案足夠好。在一些快速閱讀的字形集羣邊界似乎非常需要實施。我現在不需要它。 '(ord(s [k])&0xc0)== 0x80'與「\ x80」相同<= s [k] <=「\ xBF」'?我確實發現這個整齊製作的 – runfalk 2011-05-18 14:08:21

+1

是的,它們是相同的。我有點習慣於用C編寫UTF-8處理代碼,這解釋了風格。使用你最喜歡的風格。 – 2011-05-18 19:58:02

0

如果你可以確保你的字符的utf-8表示只有2字節長,你應該可以安全地將unicode字符串分成150個字符(對大多數歐洲編碼來說應該是這樣)。但是utf-8是可變寬度編碼。因此,可能會將unicode字符串拆分爲單個字符,將每個字符轉換爲utf-8並填充緩衝區,直至達到最大塊大小......如果高吞吐量是必須的,則這可能效率低下並且存在問題...

+0

將會有更多的歐洲編碼。中國人和日本人肯定會代表。高吞吐量不是必需的。我希望有一個更漂亮的解決方案。 – runfalk 2011-05-18 11:02:26

+3

那麼,utf-8轉換的字符長度最多爲4個字節。所以75個字符乘4的垃圾使得300個字節處於非常安全的一邊。 – 2011-05-18 11:03:55

5

UTF-8具有特殊的性質,所有的連續字符0x80 –​​(開始位10)。所以只要確保你在一個之前不分裂。

線沿線的東西:

def split_utf8(s, n): 
    if len(s) <= n: 
     return s, None 
    while ord(s[n]) >= 0x80 and ord(s[n]) < 0xc0: 
     n -= 1 
    return s[0:n], s[n:] 

應該做的伎倆。

+0

'如果len(s <= n)'??? – 2011-05-18 11:39:34

+0

@John Fixxored。 – badp 2011-05-18 11:44:17

-2
其通過設計具有固定每個字符的長度,例如 utf-32

使用Unicode編碼:

>>> u_32 = u'Юникод'.encode('utf-32') 
>>> u_32 
'\xff\xfe\x00\x00.\x04\x00\x00=\x04\x00\x008\x04\x00\x00:\x04\x00\x00>\x04\x00\x 
004\x04\x00\x00' 
>>> len(u_32) 
28 
>>> len(u_32)%4 
0 
>>> 

編碼可以發送任何大小的塊之後,而不破壞字符

(大小必須是4個的倍數字節)
+1

這是不可能的,因爲服務器需要UTF-8 – runfalk 2011-05-18 13:31:53

2

經過測試。

def split_utf8(s , n): 
    assert n >= 4 
    start = 0 
    lens = len(s) 
    while start < lens: 
     if lens - start <= n: 
      yield s[start:] 
      return # StopIteration 
     end = start + n 
     while '\x80' <= s[end] <= '\xBF': 
      end -= 1 
     assert end > start 
     yield s[start:end] 
     start = end 
相關問題