2013-01-09 3 views
18

w dużym zbiorze danych Mam pewne dane, które wygląda następująco:Jak zweryfikować, czy ciąg znaków UTF-8 zawiera MAL-kodowane znaki

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

mam otwarty plik w edytorze hex i metę dane surowego bajtu za pomocą algorytmu wykrywającego kodowanie znaków (http://code.google.com/p/juniversalchardet/) i jest wykrywany pozytywnie jako UTF-8.

Wydaje mi się, że źródło danych błędnie zinterpretowało oryginalny zestaw znaków i zapisało prawidłowy kod UTF-8 jako wynik, który otrzymałem.

Chciałbym sprawdzić dane najlepiej jak potrafię. Czy są jakieś heurystyki/algorytmy, które mogą mi pomóc w walidacji?

+1

Co jest źródłem tutaj? Czy przesyłasz oryginalne dane do źródła? Na pierwszy rzut oka powiedziałbym, że próbowałeś i popchnąłeś apostrofy cp-1252 bez ich konwersji na odpowiednie odpowiedniki UTF-8 ... – fge

+0

Musisz pokazać, jak czytasz dane z zestawu danych i jak prezentujesz konkretne dane użytkownikowi końcowemu/sobie. Na przykład, czy używasz 'FileReader' do odczytu i' System.out.println() ', aby go przedstawić? Musisz powiedzieć jednemu lub obu, aby używał UTF-8 zamiast domyślnego zestawu znaków platformy, który jest rozpoznawalny jako CP1252. – BalusC

+0

To wygląda jak źródło danych UTF-8 (z U + 2019 '' 'zakodowane poprawnie jako oktety' e2 80 99') dekodowane przy użyciu jedno bajtowego kodowania Windows-1252 (gdzie są one interpretowane jako punkty kodowe U + 00e2 U + 20ac U + 2122 - 'â" ¢ '. – McDowell

Odpowiedz

34

Nie możesz tego zrobić, gdy masz ciąg znaków, musisz to zrobić, dopóki wciąż masz nieprzetworzone dane wejściowe. Kiedy już masz ciąg, nie ma sposobu, aby automatycznie stwierdzić, czy faktycznie wprowadzono dane wejściowe bez poważnych testów. Na przykład:

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 

} 

Jeśli nadal masz dostęp do wejścia surowca, można sprawdzić, czy tablica bajtów ilościach, aby w pełni prawidłowe UTF-8 sekwencji bajtów z tym:

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; 
    }  
} 

Można również użyć CharsetDecoder ze strumieniami domyślnie generuje wyjątek, gdy tylko widzi niepoprawne bajty w danym kodowaniu.

+0

Jest to zdecydowanie najprostsze rozwiązanie, jakie do tej pory znalazłem. – Chepech

-4

Jeśli używasz HTML5 wtedy wystarczy dodać <meta charset="UTF-8"> wewnątrz <head>

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

Powiązane problemy