2015-06-01 6 views
7

Abbiamo migrato di recente la nostra applicazione a JDK 8 da JDK 7. Dopo la modifica, abbiamo riscontrato un problema con il seguente snippet di codice.Java 8 modifica in decodifica UTF-8

String output = new String(byteArray, "UTF-8"); 

La matrice di byte può contenere validi UTF-8 sequenze di byte. La stessa matrice di byte su UTF-8 decodifica, comporta due stringhe di differenza su Java 7 e 8. Java

Secondo le answer a questo SO post, Java 8 "correzioni" un errore in Java 7 e sostituisce valido UTF-8 sequenze di byte con una stringa di sostituzione, che è in accordo con le specifiche UTF-8.

Ma ci piacerebbe restare con la versione di Java 7 della stringa decodificata.

abbiamo cercato di utilizzare CharsetDecoder con CodingErrorAction come REPLACE, e ignorare RELAZIONE su Java 8. Eppure, non siamo stati in grado di generare la stessa stringa di Java 7.

Possiamo farlo con una tecnica di ragionevole complessità?

+2

Inserisci l'input esatto 'byteArray' (minimo estratto da esso), in modo che possiamo riprodurre il tuo problema. –

+1

Se il tuo problema è che ci sono coppie surrogate codificate erroneamente, 'CodingErrorAction' non ti aiuterà. Pensa a 'UTF-8' e' modificato UTF-8' come due codifiche completamente diverse. In tal caso non ti aspetteresti che un'opzione di ripristino dell'errore passi a un'altra codifica, vero? Quindi, quello di cui hai bisogno, è un'implementazione 'Charset' alternativa, ma ciò non sarebbe più semplice delle cinque righe della risposta collegata. – Holger

+0

@Holger Non sono sicuro che ci siano "solo" coppie surrogate erroneamente codificate, il codice effettivamente fa qualcosa come questa nuova stringa (hmac.doFinal (byteArray), "UTF-8"). Qui hmac è un'istanza di MAC. Questa non è assolutamente una stringa codificata UTF-8 valida (anche parti di esso). Se seguiamo la soluzione menzionata nell'altro post, otteniamo un'eccezione per i caratteri UTF-8 non validi. – Jiraiya

risposta

7

Dai puntatori forniti da @Holger, era chiaro che dovevamo scrivere un CharsetDecoder personalizzato.

ho copiato sulla versione di OpenJDK di classe sun.nio.cs.UTF_8, rinominato a CustomUTF_8 e usato per costruire una stringa in questo modo

String output = new String(bytes, new CustomUTF_8()); 

Ho intenzione di effettuare molti test di verifica attraversare le uscite generate su Java 7 e Java 8. Questa è una soluzione provvisoria mentre sto cercando di risolvere il problema reale del passaggio dell'output da hmac direttamente a String senza Base64 che lo codifica per primo.

String output = new String(Base64.Encoder.encode(bytes), Charset.forname("UTF-8")); 
+0

Se il test va bene, sarebbe una buona idea rilasciarlo come libreria e inserirlo in Maven Centrale, quindi altre persone con lo stesso problema possono usarlo. –

+0

@TagirValeev Penso che sia una cattiva idea per rendere più facile per le persone farlo. La classe CharsetDecoder traduce una sequenza di byte in un set di caratteri specifico in una sequenza di caratteri Unicode a sedici bit. Il lavoro di patch a questo livello è pericoloso perché non posso essere molto sicuro che una sequenza di caratteri Unicode a sedici bit venga interpretata in due versioni della JVM. – Jiraiya