2009-11-04 11 views
31

Biorąc pod uwagę tablicę bajtów przedstawiającą tekst w nieznanym kodowaniu (zwykle UTF-8 lub ISO-8859-1, ale niekoniecznie tak), jaki jest najlepszy sposób na uzyskać domysły na temat najbardziej prawdopodobnego kodowania (w Javie)?Zgadywanie kodowania tekstu reprezentowanego jako bajt [] w Javie

Warto zauważyć:

  • Brak dodatkowych meta-dane są dostępne. Tablica bajtów jest dosłownie jedynym dostępnym wejściem.
  • Algorytm wykrywania nie będzie w 100% poprawny. Jeśli algorytm jest poprawny, oznacza więcej niż 80% przypadków, które są wystarczająco dobre.
+2

http://stackoverflow.com/questions/373081/ może pomocy – Chris

Odpowiedz

28

Następująca metoda rozwiązuje problem za pomocą juniversalchardet, który jest portem Java biblioteki wykrywania kodowania Mozilli.

public static String guessEncoding(byte[] bytes) { 
    String DEFAULT_ENCODING = "UTF-8"; 
    org.mozilla.universalchardet.UniversalDetector detector = 
     new org.mozilla.universalchardet.UniversalDetector(null); 
    detector.handleData(bytes, 0, bytes.length); 
    detector.dataEnd(); 
    String encoding = detector.getDetectedCharset(); 
    detector.reset(); 
    if (encoding == null) { 
     encoding = DEFAULT_ENCODING; 
    } 
    return encoding; 
} 

Powyższy kod został przetestowany i działa zgodnie z przeznaczeniem. Po prostu dodaj juniversalchardet-1.0.3.jar do ścieżki klas.

Testowałem zarówno juniversalchardet, jak i jchardet. Mam ogólne wrażenie, że juniversalchardet zapewnia lepszą dokładność wykrywania i ładniejszy interfejs API dwóch bibliotek.

+0

moje wymaganie projektu jest, jeśli dane nie są w utf8 (po wykryciu), a następnie przekonwertować go na utf8, jak to zrobić? –

+0

@ kodowanie_idiot użyj kodowania "zgadnij", aby przekonwertować na ciąg, a następnie pobierz bajty utf-8: 'new String (bytes, guessedEncoding) .getBytes (" utf-8 ")'. –

+0

Teraz projekt jest na [github] (https://github.com/albfernandez/juniversalchardet) – bigspawn

0

Wyjazd jchardet

+7

Proszę opracować - dlaczego uważasz, że jchardet jest najlepszą biblioteką w okolicy? – knorv

+0

@chi jak przekonwertować na utf8, jeśli kodowanie nie jest utf8. –

-1

Powinny być rzeczy już dostępny

wyszukiwanie google okazało się icu4j

lub

http://jchardet.sourceforge.net/

+2

Wiem, jak korzystać z Google, ale pytanie dotyczy "najlepszego sposobu [..]". Co jest najlepsze, icu4j, jchardet lub jakąś inną bibliotekę? – knorv

1

odpowiedź Chi wydaje się najbardziej obiecujący dla rzeczywistego użytkowania. Chcę tylko dodać, że zgodnie z Joel Spolsky, Internet Explorer używał częstotliwości oparte na zgadywaniu algorytm w swoim czasie:

http://www.joelonsoftware.com/articles/Unicode.html

Z grubsza rzecz biorąc, cały zakładany-do-tekst jest kopiowany, a analizowane w każdym możliwym kodowaniu. Który wynik najlepiej pasuje do przeciętnego słowa (i litery?) W zakresie częstotliwości, wygrywa. Nie mogę szybko sprawdzić, czy jchardet używa tego samego podejścia, więc pomyślałem, że wspomnę o tym na wszelki wypadek.

-1

Bez wskaźnika kodowania nigdy się nie dowiesz. Możesz jednak dokonać inteligentnych przypuszczeń. Zobacz moją odpowiedź na to pytanie,

How to determine if a String contains invalid encoded characters

Użyj validUTF8() metody. Jeśli zwraca true, traktuj to jako UTF8, w przeciwnym razie jako Latin-1.

+0

Co z przypadkami, w których nie jest to UTF-8? – knorv

+0

Jeśli nie jest to UTF-8, ślepo nazywanie go Latin-1 nie jest dobrym pomysłem. Byłoby lepiej użyć ICU, jchardet lub jednego z innych narzędzi wymienionych na tej stronie, aby dokonać inteligentnego odgadnięcia. –

3

Oto mój ulubiony: http://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding

To działa tak:

  • Jeśli jest UTF-8 lub UTF-16 BOM, powrót to kodowanie.
  • Jeśli żaden z bajtów nie ma zestawu bitów wyższego rzędu, zwróć kod ASCII (lub możesz wymusić na nim powrót do domyślnego kodowania 8-bitowego).
  • Jeśli istnieją bajty z ustawionym wysokim bitem, ale są one ułożone we właściwych wzorcach dla UTF-8, zwróć kod UTF-8.
  • W przeciwnym razie zwróć domyślne kodowanie platformy (np. Windows-1252 w systemie Windows z angielską wersją językową).

Może wydawać się zbyt uproszczona, ale w mojej codziennej pracy jest ponad 90% dokładna.