2015-06-11 166 views
7

已經有相當一些幫助,但我仍然困惑。Python長度的Unicode字符串混淆

我有一個unicode字符串是這樣的:

title = u'test' 
title_length = len(title) #5 

但是!我需要len(title)爲6.客戶期望它是6,因爲它們似乎以與我在後端不同的方式計算。

作爲一種解決方法,我寫了這個小助手,但我相信它可以得到改進(對編碼有足夠的瞭解),或者甚至是錯誤的。

title_length = len(title) + repr(title).count('\\U') #6 

1.是否有更好的方法獲得長度爲6? :-)

我假設我(Python)計數的Unicode字符的數量是5.客戶端正在計算字節數?

2.我的邏輯會中斷其他需要4個字節的Unicode字符嗎?

運行Python 2.7 ucs4。

+3

客戶端統計UTF-16代理對。 –

+0

當我嘗試運行這兩行時,它顯示長度爲6. – ssundarraj

+1

@ssundarraj:查看我的答案;您正在運行Python 2 UCS2版本。使用Python 3.3或更高版本,或者讓自己成爲UCS4版本。 –

回答

6

您有5 碼點。其中一個代碼點位於Basic Multilingual Plane之外,這意味着對於那些代碼點has to use two code units for the character的UTF-16編碼。

換句話說,客戶端依賴於實現細節,並且做錯了什麼。他們應該計算代碼,而不是代碼單位。有幾個平臺發生這種情況很有規律; Python 2 UCS2構建就是這樣,但Java開發人員經常會忘記差異,Windows API也是如此。

您可以將文本編碼爲UTF-16並將字節數除以2(每個UTF-16代碼單元爲2個字節)。挑utf-16-leutf-16-be變體不包括在長度的BOM

title = u'test' 
len_in_codeunits = len(title.encode('utf-16-le')) // 2 

如果正在使用Python 2(以及由u前綴來你可能是字符串判斷),考慮到有2種不同的Python,取決於你如何構建它。根據構建時配置開關,您可以使用UCS-2或UCS-4版本;前者也使用內部代理,並且您的title值長度也將爲6。見Python returns length of 2 for single Unicode character string

+0

客戶端確實是Java,你怎麼知道他們計數UTF-16代理對?難道它不是UTF-8或UTF-32嗎?我能確定它們總是*計數2個代碼單元,取決於它可能更多的代碼點嗎?你的計數方法看起來確實更優雅。 :-)非常感謝這個偉大的解釋! – kev

+0

如果統計不同UTF編解碼器中的代碼單元(UTF-8爲8,UTF-32爲5),計數將大不相同。是的,UTF-16使用一個或兩個代碼單元,總是在我的答案中看到維基百科鏈接。Java代碼可以修復;請參閱[JSR-204](https://jcp.org/en/jsr/detail?id=204)和['codePointCount()'方法](http://docs.oracle.com/javase/7/文檔/ API /爪哇/郎/ String.html#codePointCount(INT,%20int))。 –