2015-06-01 12 views
7

Niedawno przenieśliśmy naszą aplikację do JDK 8 z JDK 7. Po zmianie wystąpił problem z następującym fragmentem kodu.Zmiana 8 Java w dekodowaniu UTF-

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

Tablica bajtów może zawierać nieprawidłowe sekwencje bajtów UTF-8. Ta sama tablica bajtów na UTF-8 dekodowania, skutkuje dwóch ciągów różnicowych na Java i Java 7 8.

Według answer do tego SO post, Java 8 „poprawek” błędu w Java 7 i zastępuje nieprawidłowy UTF-8 sekwencje bajtów z ciągiem zastępującym, który jest zgodny ze specyfikacją UTF-8.

Ale chcielibyśmy trzymać się wersji dekodowanego łańcucha Java 7.

Staraliśmy się wykorzystać CharsetDecoder z CodingErrorAction jak REPLACE, Raport i ignorować na Java 8. Still, nie byliśmy w stanie wygenerować ten sam ciąg jako Java 7.

Możemy to zrobić za pomocą techniki rozsądne złożoność?

+2

Proszę napisać dokładny wpis 'byteArray' (minimalny fragment z niego), abyśmy mogli odtworzyć Twój problem. –

+1

Jeśli masz problem z nieprawidłowo zakodowanymi parami zastępczymi, "CodingErrorAction" nie pomoże. Pomyśl o 'UTF-8' i' modified UTF-8' jako dwóch całkowicie różnych kodowaniach. W takim przypadku nie spodziewałbyś się, że opcja odzyskiwania po błędzie zostanie przełączona na inne kodowanie, prawda? Zatem potrzebna jest alternatywna implementacja 'Charset', ale nie będzie to prostsze niż pięć linii połączonej odpowiedzi. – Holger

+0

@Holger Nie jestem pewien, czy istnieją "tylko" błędnie zakodowane pary zastępcze, kod faktycznie robi coś takiego jak ten nowy ciąg (hmac.doFinal (byteArray), "UTF-8"). Tutaj hmac jest instancją MAC. Nie jest to w żadnym razie prawidłowy kodowany ciąg znaków UTF-8 (nawet jego części). Jeśli zastosujemy rozwiązanie wspomniane w drugim poście, otrzymamy wyjątek dla nieprawidłowych znaków UTF-8. – Jiraiya

Odpowiedz

7

Ze wskaźników dostarczonych przez @Holger, Było jasne, że musieliśmy napisać niestandardowy CharsetDecoder.

I skopiowane wersję OpenJDK za klasy sun.nio.cs.UTF_8, przemianowano go CustomUTF_8 i wykorzystał je skonstruować ciąg jak tak

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

Planuję uruchomić intensywne testy przejechać weryfikacji wyjść generowanych na Java 7 i Java 8. Jest to rozwiązanie tymczasowe, podczas gdy próbuję naprawić rzeczywisty problem z przekazywaniem danych wyjściowych z hmac bezpośrednio do String bez kodowania Base64 najpierw do.

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

Jeśli testowanie idzie dobrze, dobrze byłoby wydać go jako bibliotekę i umieścić w Maven Centralny, więc inni ludzie z tym samym problemem mogą z niego korzystać. –

+0

@TagirValeev Myślę, że to zły pomysł, aby ułatwić ludziom to zrobić. Klasa CharsetDecoder tłumaczy ciąg bajtów w określonym zestawie znaków na sekwencję szesnastobitowych znaków Unicode. Poprawki na tym poziomie są niebezpieczne, ponieważ nie jestem pewien, czy sekwencja szesnastobitowych znaków Unicode jest interpretowana w dwóch wersjach JVM. – Jiraiya