2013-01-09 4 views
18

In un grande insieme di dati Ho alcuni dati che assomiglia a questo:Come convalidare se una stringa UTF-8 contiene caratteri mal codificato

"guide (but, yeah, it’s okay to share it with ‘em)." 

ho aperto il file in un editor esadecimale e fuggi i dati di byte non elaborati tramite un algoritmo di rilevamento della codifica dei caratteri (http://code.google.com/p/juniversalchardet/) ed è rilevato positivamente come UTF-8.

Mi sembra che la fonte dei dati abbia interpretato male il set di caratteri originale e abbia scritto UTF-8 valido come output che ho ricevuto.

Mi piacerebbe convalidare i dati al meglio che posso. Ci sono delle euristiche/algoritmi là fuori che potrebbero aiutarmi a fare una pugnalata alla convalida?

+1

Qual è la fonte qui? Hai inviato i dati originali a detta fonte? Ad una prima occhiata direi che hai provato e premuto gli apostrofi cp-1252 senza che siano convertiti in equivalenti UTF-8 appropriati ... – fge

+0

Devi mostrare come stai leggendo i dati particolari dal set di dati e come stai presentando i dati particolari all'utente finale/te stesso. Ad esempio, stai usando 'FileReader' per leggerlo e' System.out.println() 'per presentarlo? Devi dire a uno oa entrambi di utilizzare UTF-8 invece del set di caratteri predefinito della piattaforma che è riconoscibile come CP1252. – BalusC

+0

Sembra un'origine dati UTF-8 (con U + 2019 '' 'codificato correttamente come ottetti' e2 80 99') decodificato usando la codifica Windows-1252 a byte singolo (dove vengono interpretati come i punti di codice U + 00e2 U + 20ac U + 2122 - ''. – McDowell

risposta

34

Non puoi farlo una volta che hai la stringa, devi farlo mentre hai ancora l'input raw. Una volta ottenuta la stringa, non è possibile stabilire automaticamente se ’ è stato effettivamente utilizzato come input senza alcuni test seriamente fragili. Per esempio:

public static boolean isUTF8MisInterpreted(String input) { 
      //convenience overload for the most common UTF-8 misinterpretation 
      //which is also the case in your question 
     return isUTF8MisInterpreted(input, "Windows-1252"); 
} 

public static boolean isUTF8MisInterpreted(String input, String encoding) { 

    CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); 
    CharsetEncoder encoder = Charset.forName(encoding).newEncoder(); 
    ByteBuffer tmp; 
    try { 
     tmp = encoder.encode(CharBuffer.wrap(input)); 
    } 

    catch(CharacterCodingException e) { 
     return false; 
    } 

    try { 
     decoder.decode(tmp); 
     return true; 
    } 
    catch(CharacterCodingException e){ 
     return false; 
    }  
} 

public static void main(String args[]) { 
    String test = "guide (but, yeah, it’s okay to share it with ‘em)."; 
    String test2 = "guide (but, yeah, it’s okay to share it with ‘em)."; 
    System.out.println(isUTF8MisInterpreted(test)); //true 
    System.out.println(isUTF8MisInterpreted(test2)); //false 

} 

Se hai ancora accesso a ingresso grezzo, è possibile vedere se un array di byte pari a pienamente validi UTF-8 sequenze di byte con questo:

public static boolean isValidUTF8(byte[] input) { 

    CharsetDecoder cs = Charset.forName("UTF-8").newDecoder(); 

    try { 
     cs.decode(ByteBuffer.wrap(input)); 
     return true; 
    } 
    catch(CharacterCodingException e){ 
     return false; 
    }  
} 

è anche possibile utilizzare il CharsetDecoder con flussi, per impostazione predefinita genera un'eccezione non appena vede byte non validi nella codifica data.

+0

Questa è di gran lunga la soluzione più semplice che ho trovato finora. Grazie! – Chepech

-4

Se si utilizza HTML5 poi basta aggiungere il <meta charset="UTF-8"> all'interno del <head>

per HTML4 <meta http-equiv="Content-type" content="text/html;charset=UTF-8">

Problemi correlati