utf8 - La codificación de cadenas de conversión de Ruby de ISO-8859-1 a UTF-8 no funciona
ruby encode utf-8 (2)
Hay una diferencia entre force_encoding y encode . El primero establece la codificación para la cadena, mientras que el último realmente transcodifica el contenido de la cadena a la nueva codificación. En consecuencia, el siguiente código causa su problema:
string = "Norrlandsvägen"
string.force_encoding(''iso-8859-1'')
puts string.encode(''utf-8'') # Norrlandsvägen
Mientras que el siguiente código en realidad codificará correctamente sus contenidos:
string = "Norrlandsvägen".encode(''iso-8859-1'')
string.encode!(''utf-8'')
Aquí hay un ejemplo que se ejecuta en irb
:
irb(main):023:0> string = "Norrlandsvägen".encode(''iso-8859-1'')
=> "Norrlandsv/xE4gen"
irb(main):024:0> string.encoding
=> #<Encoding:ISO-8859-1>
irb(main):025:0> string.encode!(''utf-8'')
=> "Norrlandsvägen"
irb(main):026:0> string.encoding
=> #<Encoding:UTF-8>
Estoy tratando de convertir una cadena de codificación ISO-8859-1 a UTF-8, pero parece que no puedo hacer que funcione. Aquí hay un ejemplo de lo que hice en irb.
irb(main):050:0> string = ''Norrlandsvägen''
=> "Norrlandsvägen"
irb(main):051:0> string.force_encoding(''iso-8859-1'')
=> "Norrlandsv/xC3/xA4gen"
irb(main):052:0> string = string.encode(''utf-8'')
=> "Norrlandsvägen"
No estoy seguro de por qué Norrlandsvägen en iso-8859-1 se convertirá en Norrlandsvägen en utf-8.
He intentado codificar, codificar, codificar (destinationEncoding, originalEncoding), iconv, force_encoding y todo tipo de soluciones de trabajo extrañas en las que podía pensar pero nada parece funcionar. ¿Puede alguien ayudarme / señalarme en la dirección correcta?
Novato Ruby todavía tirando del pelo como loco, pero sintiéndose agradecido por todas las respuestas aquí ... :)
Antecedentes de esta pregunta: estoy escribiendo una joya que descargará un archivo xml de algunos sitios web (que tendrá la codificación iso-8859-1) y lo guardará en un almacenamiento y me gustaría convertirlo primero a utf-8. Pero las palabras como Norrlandsvägen siguen arruinándome. ¡Realmente cualquier ayuda sería muy apreciada!
[ACTUALIZACIÓN]: me di cuenta de que ejecutar pruebas como esta en la consola irb podría darme comportamientos diferentes, así que esto es lo que tengo en mi código actual:
def convert_encoding(string, originalEncoding)
puts "#{string.encoding}" # ASCII-8BIT
string.encode(originalEncoding)
puts "#{string.encoding}" # still ASCII-8BIT
string.encode!(''utf-8'')
end
pero la última línea me da el siguiente error:
Encoding::UndefinedConversionError - "/xC3" from ASCII-8BIT to UTF-8
Gracias a la respuesta de /xC3
continuación, noté que /xC3
aparece realmente en irb si ejecutas:
irb(main):001:0> string = ''ä''
=> "ä"
irb(main):002:0> string.force_encoding(''iso-8859-1'')
=> "/xC3/xA4"
También traté de asignar una nueva variable al resultado de string.encode(originalEncoding)
pero obtuve un error aún más extraño:
newString = string.encode(originalEncoding)
puts "#{newString.encoding}" # can''t even get to this line...
newString.encode!(''utf-8'')
y el error es Encoding::UndefinedConversionError - "/xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to ISO-8859-1
Todavía estoy bastante perdido en todo este lío de codificación, pero estoy muy agradecido por todas las respuestas y la ayuda que todos me han brindado. ¡Gracias una tonelada! :)
Usted asigna una cadena, en UTF-8. Contiene ä
. UTF-8 representa ä
con dos bytes.
string = ''ä''
string.encoding
# => #<Encoding:UTF-8>
string.length
# 1
string.bytes
# [195, 164]
Luego, fuerza los bytes a interpretar como si fueran ISO-8859-1, sin cambiar realmente la representación subyacente. Esto ya no contiene ä
. Contiene dos caracteres, Ã
y ¤
.
string.force_encoding(''iso-8859-1'')
# => "/xC3/xA4"
string.length
# 2
string.bytes
# [195, 164]
Luego lo UTF-8
en UTF-8
. Como esto no es una reinterpretación sino una traducción, mantienes los dos caracteres, pero ahora está codificado en UTF-8:
string = string.encode(''utf-8'')
# => "ä"
string.length
# 2
string.bytes
# [195, 131, 194, 164]
Lo que te falta es el hecho de que originalmente no tienes una cadena ISO-8859-1, como lo harías con tu servicio web; tienes un galimatías. Afortunadamente, esto es todo en tus pruebas de consola; si lee la respuesta del sitio web utilizando la codificación de entrada adecuada, todo debería funcionar bien.
Para su prueba de consola, demostremos que si comienza con una cadena ISO-8859-1 adecuada, todo funciona:
string = ''Norrlandsvägen''.encode(''iso-8859-1'')
# => "Norrlandsv/xE4gen"
string = string.encode(''utf-8'')
# => "Norrlandsvägen"
EDITAR Para su problema específico, esto debería funcionar:
require ''net/https''
uri = URI.parse("https://rusta.easycruit.com/intranet/careerbuilder_se/export/xml/full")
options = {
:use_ssl => uri.scheme == ''https'',
:verify_mode => OpenSSL::SSL::VERIFY_NONE
}
response = Net::HTTP.start(uri.host, uri.port, options) do |https|
https.request(Net::HTTP::Get.new(uri.path))
end
body = response.body.force_encoding(''ISO-8859-1'').encode(''UTF-8'')