2012-04-06 15 views
11

Ho una coda di messaggi di testo in Redis. Diciamo che un messaggio in redis è qualcosa del tipo:Rails, Heroku e sequenza di byte non valida nell'errore UTF-8

"niño" 

(individuare il carattere non standard).

L'app per binari visualizza la coda dei messaggi. Quando eseguo il test localmente (Rails 3.2.2, Ruby 1.9.3) tutto va bene, ma su Heroku cedar (Rails 3.2.2, credo che ci sia ruby ​​1.9.2) Ottengo l'infame errore: ActionView::Template::Error (invalid byte sequence in UTF-8)

Dopo leggendo e rileggendo tutto ciò che ho potuto trovare online sono ancora bloccato su come risolvere questo problema.

Qualsiasi aiuto o punto nella giusta direzione è molto apprezzato!

modifica:

Sono riuscito a trovare una soluzione. Ho finito per utilizzare Iconv:

string = Iconv.iconv('UTF-8', 'ISO-8859-1', message)[0] 

Nessuna delle risposte suggerite che ho trovato sembra funzionare nel mio caso.

+0

ho installato tramite heroku labs ruby ​​1.9.3, ma ottengo ancora lo stesso errore: | – klaut

+2

Quando si richiede Iconv in Ruby 1.9.3 si ottiene questo avviso: 'iconv sarà deprecato in futuro, usare invece la codifica String #. L'equivalente della soluzione sarà qualcosa del tipo:' string.force_encoding ('iso-8859- 1 '). codificare (' utf-8') '. – matt

+2

Oppure 'string = message.encode ('utf-8', 'iso-8859-1')' potrebbe essere migliore. – matt

risposta

38

Su Heroku, quando la vostra applicazione riceve il messaggio "Nino" da Redis, esso è in realtà sempre i quattro byte:

0x6e 0x69 0xf1 0x6f 

che, se interpretato come ISO-8859-1 corrispondono ai personaggi n, i, ñ e o.

Tuttavia, l'app Rails presuppone che questi byte debbano essere interpretati come UTF-8 e, a un certo punto, tenta di decodificarli in questo modo. Il terzo byte in questa sequenza, 0xf1 assomiglia a questo:

1 1 1 1 0 0 0 1 

Se si confronta questo al table on the Wikipedia page, è possibile vedere questo byte è il byte iniziale di un carattere quattro byte (che corrisponde al modello 11110xxx), e come tale dovrebbe essere seguito da altri tre byte di continuazione che corrispondono tutti allo schema 10xxxxxx. Non lo è, invece il byte successivo è 0x6f (01101111), quindi questa è una sequenza di byte utf-8 non valida e ottieni l'errore che vedi.

Usando:

string = message.encode('utf-8', 'iso-8859-1') 

(o l'equivalente Iconv) dice a Ruby per leggere message come ISO-8859-1 codificato, e quindi per creare la stringa equivalente in codifica UTF-8, che è quindi possibile utilizzare senza problemi. (Un'alternativa potrebbe essere quella di usare force_encoding per dire a Ruby la corretta codifica della stringa, ma questo probabilmente causerà problemi in seguito quando proverai a mescolare le stringhe UTF-8 e ISO-8859-1).

In UTF-8, la stringa "niño" corrisponde ai byte:

0x6e 0x69 0xc3 0xb1 0x6f 

noti che il primo, il secondo e ultimo byte sono uguali. Il carattere ñ è codificato come i due byte 0xc3 0xb1.Se li scrivi in ​​binario e li confronti con la tabella nell'articolo di Wikipedia, vedrai che codificano 0xf1, che è la codifica ISO-8859-1 di ñ (poiché i primi 256 codecoint unicode corrispondono a ISO-8859-1) .

Se si prende questi cinque byte e trattarli come ISO-8859-1, allora essi corrispondono alla stringa

niño 

Guardando il ISO-8859-1 codepage, 0xc3 mappe di Â, e le mappe 0xB1 a ±.

Quindi, ciò che accade sul computer locale è che la tua app riceve i cinque byte 0x6e 0x69 0xc3 0xb1 0x6f da Redis, che è la rappresentazione UTF-8 di "niño". Su Heroku riceve i quattro byte 0x6e 0x69 0xf1 0x6f, che è la rappresentazione ISO-8859-1.

La vera soluzione al tuo problema sarà di assicurarti che le stringhe che vengono inserite in Redis siano già tutte UTF-8 (o almeno la stessa codifica). Non ho usato Redis, ma da quello che posso dire da un breve Google, non si occupa delle codifiche di stringhe, ma restituisce semplicemente tutti i byte che sono stati dati. Dovresti considerare qualunque processo stia inserendo i dati in Redis e assicurarsi che gestisca correttamente la codifica.

+0

Molto accurato. +1 – coreyward

+0

risposta molto buona, grazie! – klaut

+2

wow, ecco come dovrebbero apparire le risposte! – Cristian

Problemi correlati