2010-07-01 11 views
10

Mam obecnie problemy z wynikami z api amazon.jak przekonwertować kodowanie znaków z ruby ​​1.9

usługa zwraca ciąg znaków Unicode z: Learn Objective \ \ x80 \ XE2 x93C na Mac (Dowiedz serii)

z Ruby 1.9.1 łańcuch nie mógłby nawet po przetworzeniu:

REXML::ParseException: #<Encoding::CompatibilityError: incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)> 

... 

Exception parsing 

Line: 1 

Position: 1636 

Last 80 unconsumed characters: 

Learn Objective–C on the Mac (Learn Series) 
+2

Gorąco polecam lekturę * Absolutne minimum Każdy programista Absolutnie, pozytywnie musi wiedzieć o Unicode i zestawach znaków (bez wymówek!) * (http://www.joelonsoftware.com/articles/Unicode.html), nawet jeśli już jesteś fa współpracownik z kodowaniem i takimi. – ewall

+2

Ostatnio przeczytałem artykuł o katechizowaniu w 1.9 autorstwa Yehudy Katza i pomyślałem: WTF ?! (http://yehudakatz.com/2010/05/17/encodings-unabridged/) Twój artykuł jest znakomity. – phoet

Odpowiedz

29

Jako punkty wyjątku, Twój ciąg znaków jest kodowany ASCII-8BIT. Powinieneś zmienić kodowanie. Jest long story o tym, ale jeśli jesteś zainteresowany w szybkim rozwiązaniu tylko force_encoding na strunie zanim zrobisz żadnego przetwarzania:

s = "Learn Objective\xE2\x80\x93C on the Mac" 
# => "Learn Objective\xE2\x80\x93C on the Mac" 
s.encoding 
# => #<Encoding:ASCII-8BIT> 
s.force_encoding 'utf-8' 
# => "Learn Objective–C on the Mac" 
+0

jest to kwestia odpowiedzi, która jest wysyłana z serwisu Amazon? powinien ustawić inny typ zawartości? – phoet

+0

Nie pracowałem z AWS, więc nie wiem, jak ten ciąg został załadowany, ale możesz ustawić domyślne kodowanie na poziomie aplikacji (Ruby), więc jest szansa, że ​​to rozwiąże problem - więcej na temat łącza w odpowiedź. BTW, nie sądzę, że w ogóle istnieje, Ruby po prostu nie (i nie powinien) próbować odgadnąć, które kodowanie ciągu, który odbiera, jest w. –

+0

Prawdopodobnie; oznaczałoby to, że zajmie się nim HTTParty. –

25

rozwiązanie Mladen za działa, jeśli wszystko, co jest zakodowane w ASCII-8bit rzeczywistości może być przekształcony bezpośrednio do UTF-8. Zniekształca się, gdy występują 1 znaki, które są nieprawidłowe lub 2) niezdefiniowane w UTF-8. Jednak będzie to działać (w 1.9.2 i do góry.

new_str = s.encode('utf-8', 'binary', :invalid => :replace, 
    :undef => :replace, :replace => '') 

ASCII 8BIT jest skutecznie konwertuje kod binarny to kodowanie na UTF-8, a właściwie do czynienia z nieprawidłowymi i niezdefiniowanych bohaterów. Niepoprawną opcję Określa, że ​​niepoprawne znaki mają być zastąpione Opcja: undef określa, że ​​niezdefiniowane znaki mają zostać zastąpione, a opcja: replace określa, które nieważne lub niezdefiniowane znaki powinny zostać zastąpione przez. W tym przypadku zdecydowałem się po prostu je usunąć

+0

uh, ładnie wygląda! spróbuję tego! – phoet

+0

czy wypróbowałeś mechanizm ': fallback'? Próbowałem zastąpić niektóre kodowania 'windows-1252', takie jak' u00E4' dla ä, ale to się nie udało :( – phoet

+0

To właśnie uratowało mi dzień, kiedy przesyłam plik strumieniowo do treści HTTP w celu opublikowania ... Wielkie dzięki! +1 – stuartc