2012-05-05 10 views

risposta

21

Direi che "\xBF" pensa già si è codificato in UTF-8 in modo che quando si chiama encode, si pensa che si sta cercando di codificare una stringa UTF-8 in UTF-8 e non fa nulla:

>> s = "\xBF" 
=> "\xBF" 
>> s.encoding 
=> #<Encoding:UTF-8> 

\xBF non è UTF-8 valido, quindi questa è, ovviamente, una sciocchezza. Ma se si utilizza la forma di tre tesi di encode:

encode (dst_encoding, src_encoding [opzioni]) → str

[...] La seconda forma restituisce una copia di str transcodifica da src_encoding a dst_encoding.

è possibile forzare la questione dicendo encode di ignorare ciò che la stringa pensa che la sua codifica è e trattarlo come dati binari:

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

Dove s è la "\xBF" che pensa che sia UTF-8 da sopra.

Si potrebbe anche usare force_encoding su s per costringerla ad essere binario e quindi utilizzare il due argomenti encode:

>> s.encoding 
=> #<Encoding:UTF-8> 
>> s.force_encoding('binary') 
=> "\xBF" 
>> s.encoding 
=> #<Encoding:ASCII-8BIT> 
>> foo = s.encode('utf-8', :invalid => :replace, :undef => :replace) 
=> "�" 
+0

Grazie! Anche l'uso di 'ascii' come la codifica from ha funzionato. – drewinglis

+1

@drewinglis: Mi piace l'esplicitezza di "binary" (che è un alias per "ascii-8bit"), "ascii" non è esattamente la stessa cosa. –

2

Questo è fisso se si legge il file di testo di origine utilizzando un pagina di codice esplicito:

File.open('thefile.txt', 'r:iso8859-1') 
2

Se si lavora solo con i caratteri ASCII è possibile utilizzare

>> "Hello \xBF World!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace) 
=> "Hello � World!" 

Ma cosa succede se usiamo lo stesso approccio con i caratteri UTF8 validi non validi in ASCII

>> "¡Hace \xBF mucho frío!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace) 
=> "��Hace � mucho fr��o!" 

Uh oh! Vogliamo restare con l'accento. Ecco un'opzione che mantiene i caratteri UTF8 validi

>> "¡Hace \xBF mucho frío!".chars.select{|i| i.valid_encoding?}.join 
=> "¡Hace mucho frío!" 

anche in Ruby 2.1 c'è un nuovo metodo chiamato scrub che risolve questo problema

>> "¡Hace \xBF mucho frío!".scrub 
=> "¡Hace � mucho frío!" 
>> "¡Hace \xBF mucho frío!".scrub('') 
=> "¡Hace mucho frío!" 
Problemi correlati