2015-06-11 6 views
7

C'è già stato un po 'di aiuto in questo, ma sono ancora confuso.Python lunghezza della confusione stringa unicode

Ho una stringa unicode come questo:

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

Ma! Ho bisogno di len (titolo) per essere 6. I client si aspettano che sia 6 perché sembrano contare in modo diverso rispetto al backend.

Come soluzione temporanea, ho scritto questo piccolo aiuto, ma sono sicuro che può essere migliorato (con sufficiente conoscenza delle codifiche) o forse è anche sbagliato.

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

1. C'è un modo migliore di ottenere la lunghezza di essere 6? :-)

Suppongo che (Python) stia contando il numero di caratteri unicode che è 5. I client stanno contando il numero di byte?

2. La mia logica si interrompe per altri caratteri unicode che richiedono 4 byte, ad esempio?

Esecuzione di Python 2.7 ucs4.

+3

Il client conta coppie surrogate UTF-16. –

+0

Quando ho provato a eseguire queste due righe, ha mostrato la lunghezza come 6. – ssundarraj

+1

@ssundarraj: vedere la mia risposta; stai eseguendo una build di Python 2 UCS2. Utilizza Python 3.3 o versioni successive oppure crea una build UCS4. –

risposta

6

Hai 5 codepoint. Uno di questi codepoints è al di fuori dello Basic Multilingual Plane che significa la codifica UTF-16 per quei codepoint has to use two code units for the character.

In altre parole, il client si basa su un dettaglio di implementazione e sta facendo qualcosa di sbagliato. Dovrebbero contare il codice punti, non il codice unità. Ci sono diverse piattaforme in cui questo accade abbastanza regolarmente; I build di Python 2 UCS2 sono uno di questi, ma gli sviluppatori Java spesso dimenticano la differenza, così come le API di Windows.

È possibile codificare il testo su UTF-16 e dividere il numero di byte per due (ciascuna unità di codice UTF-16 è 2 byte). Scegliere la variante utf-16-le o utf-16-be di non includere un BOM nella lunghezza:

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

Se si sta utilizzando Python 2 (ea giudicare dal u prefisso alla stringa si può ben essere), tengono conto che ci sono 2 diversi gusti di Python, a seconda di come lo hai creato. A seconda di uno switch di configurazione in fase di costruzione, si avrà una build UCS-2 o UCS-4; il primo utilizza surrogati internamente allo e anche la lunghezza del valore title sarà pari a 6. Vedi Python returns length of 2 for single Unicode character string.

+0

I client sono davvero Java, come facevi a sapere che contano le coppie di surrogati UTF-16? Non potrebbe essere anche UTF-8 o UTF-32? Posso essere sicuro che * contano * sempre 2 codeunità, depistando sul codice che potrebbe essere di più? Il tuo metodo di conteggio sembra davvero più elegante. :-) Grazie mille per questa grande spiegazione! – kev

+0

I conteggi sarebbero molto diversi se contassero unità di codice in un codec UTF diverso (8 in UTF-8 e 5 in UTF-32). Sì, UTF-16 usa una o due unità di codice, sempre, vedi il link di Wikipedia nella mia risposta.Il codice Java può essere risolto; si veda [JSR-204] (https://jcp.org/en/jsr/detail?id=204) e il [metodo 'codePointCount()' (http://docs.oracle.com/javase/7/ docs/api/java/lang/String.html # codePointCount (int,% 20int)). –