2012-12-10 18 views
5

Vorrei un algoritmo o una libreria in grado di indicare se un punto Unicode è valido. Ad esempio, U+F8F8 non sembra essere un carattere Unicode valido ma è descritto come "PRIVATE_USE_AREA". Ho trovato ICU - questa è una soluzione buona/migliore?Come determinare se un carattere Unicode è valido

UPDATE: @ suggerimento di Reprogrammer (sotto) è quello di utilizzare:

CoderResult call(CharsetDecoderICU decoder, Object context, 
    ByteBuffer source, CharBuffer target, IntBuffer offsets, 
    char[] buffer, int length, CoderResult cr) 
This function is called when the bytes in the source cannot be handled, 
    and this function is meant to handle or fix the error if possible. 

Grazie. Questo sembra più complesso di quanto speravo - forse è necessariamente un problema più complesso di quanto pensassi. (Il problema comprende punti, come '<Non Private Use High Surrogate, First>' (U+D800) che sono (presumo) valida solo se seguita da almeno un altro punto di codice

UPDATE:. @Jukka scrive:

Definire “valido” Un uso privato. il punto di codice è valido secondo lo standard Unicode , non ha alcun carattere assegnato nello standard . Un punto di codice surrogato non è un dato carattere valido, ma le unità di codice surrogato possono essere utilizzate in UTF-16. La stringa Java è una sequenza di unità di codice, non i caratteri, qualsiasi unità di codice può apparire lì, ma quando si elabora una stringa come caratteri, dovrebbe essere conforme allo con i requisiti Unicode sui caratteri. - Jukka K. Korpela

Sono d'accordo che la definizione di "valido" è importante. Ho preso l'utilizzo dal sito FileFormat.Info che ha dichiarato:

U+F8F8 is not a valid unicode character. 

Sembra un sito abbastanza autorevole così ho usato il loro termine. Forse sono un po 'imprecisi

AGGIORNAMENTO: Ho provato @ Python di Ignacio in Java ma non è riuscito. Ho scritto

public void testUnicode() { 
     Pattern pattern = Pattern.compile("\\p{Cn}"); 
     System.out.println("\\u0020 "+pattern.matcher("\u0020").matches()); 
     System.out.println("A "+pattern.matcher("A").matches()); 
     System.out.println("\\uf8f8 "+pattern.matcher("\uf8f8").matches()); 
    } 

che restituiva uniformemente false, anche per i caratteri Unicode "validi". Inoltre, non ho trovato il documento \p{Cn} documentato.

+0

Hai provato CharsetCallback.Decoder http://icu-project.org/apiref/icu4j/com/ibm/icu/charset/CharsetCallback.Decoder.html? – reprogrammer

+0

Definire "valido". Un punto di codice Uso privato è valido secondo lo standard Unicode, semplicemente non ha alcun carattere assegnato nello standard. Un punto codice * surrogato * non è un dato carattere valido, ma le unità codice * surrogate * possono essere utilizzate in UTF-16. Una stringa Java è una sequenza di unità di codice, non di caratteri; qualsiasi unità di codice può apparire lì, ma quando si elabora una stringa come caratteri, dovrebbe essere conforme ai requisiti Unicode sui caratteri. –

+0

@Jukka questo è molto utile. L'ho copiato nel testo. –

risposta

3

L'approccio che si descrive in un commento alla risposta di @ IgnacioVazquez-Abrams è corretta, utilizzando la corrispondenza con modelli come "\\p{Cn}", che testano la proprietà Category (gc). Ma per U + F8F8, questa corrispondenza specifica produce correttamente false, perché la categoria di questo personaggio non è Cn ma Cs (Altro, surrogato). Se provi ad es. per U + FFFF, si diventa veri.

Le categorie Unicode in grande classe C (con nome della categoria che iniziano per C) sono:

  • Cc: Altro, controllo; caratteri di controllo, ad es. Ritorno a capo
  • Cf: Altro, formato; per esempio.il trattino morbido (invisibile, ma può influire sulla formattazione)
  • C: Altri, surrogati; non valido nei dati di carattere, ma può apparire, a coppie, in una stringa Java (che è una stringa di unità di codice, non caratteri)
  • Co: Altro, uso privato; valido nei dati di carattere, ma non ha caratteri assegnati dallo standard Unicode e non deve essere utilizzato nello scambio di informazioni tranne che per assegnazioni private (che assegnano un significato al punto di codice)
  • Cn: Altro, non assegnato; questo può significare che il punto di codice viene indicato in modo permanente come non carattere o semplicemente non assegnato, ad es. non ancora assegnato (ma può essere assegnato a un personaggio in una versione futura di Unicode)

Quindi, quando si esegue il test di validità, Cn deve essere rifiutato (con la riserva che ciò possa causare il rifiuto di un carattere valido quando il Lo standard Unicode è cambiato); Cs deve essere rifiutato quando si testano i punti del codice, ma quando si elaborano stringhe Java, si dovrebbe accettare una coppia di caratteri C quando il primo è surrogato alto e il secondo è surrogato basso (presupponendo che si desidera accettare caratteri oltre il piano multilingue di base); e la gestione di Co dipende dal fatto che si desideri considerare come validi i punti codice Uso privato.

Privato È possibile che vengano visualizzati punti di codice di utilizzo, ad esempio, nei dati destinati a essere visualizzati utilizzando un carattere con glifi assegnati a tali punti di codice. Tali caratteri sono kludgy, ma esistono, e l'approccio non è formalmente scorretto.

I punti di codice Unicode in altre classi principali devono essere trattati come caratteri oltre ogni dubbio. Ciò non significa che un'applicazione debba accettarli, ma solo che denotano correttamente i caratteri.

+0

Grazie. Impossibile trovare questo in Oracle Javadoc per 1.6 http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html ma potrebbe non averlo letto attentamente –

0

Una corrispondenza con la proprietà "Cn" Unicode indica un carattere Unicode non valido. Un esempio in Python (può essere facilmente convertito in Java):

>>> regex.match(r'\p{Cn}', u'\ud800') 
<_regex.Match object at 0x7f6d5552c120> 
>>> regex.match(r'\p{Cn}', u'a') 
>>> regex.match(r'\p{Cn}', u'\uf8f8') 
<_regex.Match object at 0x7f6d5552c198> 
+0

Questa non è una risposta molto utile in quanto non capisco la proprietà "Cn" Unicode di Python e (almeno per me) non può essere facilmente convertita in Java perché non la capisco affatto. "Cn" è una serie di regex che definiscono Unicode? –

+0

Non è di Python, è [Unicode's] (http://www.unicode.org/reports/tr44/tr44-4.html#Property_Values). Basta inserirlo in un ['Pattern'] (http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html). –

+0

Ci provo, grazie –

2

Provare a utilizzare String.codePointAt
Ecco l'API:

int java.lang.String.codePointAt(int index) 



codePointAt 
public int codePointAt(int index) 
Returns the character (Unicode code point) at the specified index. 
    The index refers to char values (Unicode code units) and ranges from 0 to length() - 1. 
If the char value specified at the given index is in the high-surrogate range, the 
    following index is less than the length of this String, and the char value at the 
    following index is in the low-surrogate range, then the supplementary code point 
    corresponding to this surrogate pair is returned. Otherwise, the char value at the 
    given index is returned. 


Parameters: 
index - the index to the char values 
Returns: 
the code point value of the character at the index 
Throws: 
IndexOutOfBoundsException - if the index argument is negative or not less than the 
    length of this string. 
+0

Questo sembra utile e lo proverò. (formattato per una lettura più semplice) –

Problemi correlati