Ruby转换字符串编码从ISO-8859-1到UTF-8不起作用

cha*_*int 8 ruby encoding utf-8 character-encoding iconv

我正在尝试将字符串从ISO-8859-1编码转换为UTF-8,但我似乎无法使其工作.这是我在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" 
Run Code Online (Sandbox Code Playgroud)

我不知道为什么 Norrlandsvägen在ISO-8859-1将被转换成Norrlandsvägen在UTF-8.

我尝试过编码,编码!,编码(destinationEncoding,originalEncoding),iconv,force_encoding,以及我能想到的各种奇怪的解决方法,但似乎没什么用.有人可以帮助我/指出我正确的方向吗?

Ruby新手仍然像疯了一样拉头发,但感谢所有回复... :)

这个问题的背景:我正在编写一个宝石,它将从一些网站下载一个xml文件(将具有iso-8859-1编码)并将其保存在存储中,我想先将其转换为utf-8.但像Norrlandsvägen这样的词语让我感到困惑.真的任何帮助将不胜感激!

[更新]:我意识到在irb控制台中运行这样的测试可能会给我不同的行为,所以这里是我在实际代码中的内容:

def convert_encoding(string, originalEncoding) 
  puts "#{string.encoding}" # ASCII-8BIT
  string.encode(originalEncoding)
  puts "#{string.encoding}" # still ASCII-8BIT
  string.encode!('utf-8')
end
Run Code Online (Sandbox Code Playgroud)

但最后一行给出了以下错误:

Encoding::UndefinedConversionError - "\xC3" from ASCII-8BIT to UTF-8
Run Code Online (Sandbox Code Playgroud)

感谢@Amadan在下面的回答,我注意到\xC3如果你运行,实际上会显示在irb中:

irb(main):001:0> string = 'ä'
=> "ä"
irb(main):002:0> string.force_encoding('iso-8859-1')
=> "\xC3\xA4"
Run Code Online (Sandbox Code Playgroud)

我还尝试为结果分配一个新变量,string.encode(originalEncoding)但得到了一个更奇怪的错误:

newString = string.encode(originalEncoding)
puts "#{newString.encoding}" # can't even get to this line...
newString.encode!('utf-8')
Run Code Online (Sandbox Code Playgroud)

而错误是 Encoding::UndefinedConversionError - "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to ISO-8859-1

我仍然在所有这些编码混乱中迷失方向,但我非常感谢所有回复并帮助每个人都给了我!万分感谢!:)

Ama*_*dan 15

您以UTF-8分配字符串.它包含ä.UTF-8表示ä两个字节.

string = 'ä'
string.encoding
# => #<Encoding:UTF-8>
string.length
# 1
string.bytes
# [195, 164]
Run Code Online (Sandbox Code Playgroud)

然后强制将字节解释为它们是ISO-8859-1,而不实际更改基础表示.这不再包含ä了.它包含两个字符,ä.

string.force_encoding('iso-8859-1')
# => "\xC3\xA4"
string.length
# 2
string.bytes
# [195, 164]
Run Code Online (Sandbox Code Playgroud)

然后你将其翻译成UTF-8.由于这不是重新解释而是翻译,你保留两个字符,但现在以UTF-8编码:

string = string.encode('utf-8')
# => "ä" 
string.length
# 2
string.bytes
# [195, 131, 194, 164]
Run Code Online (Sandbox Code Playgroud)

您缺少的是您最初没有 ISO-8859-1字符串,就像您从Web服务那样 - 您有胡言乱语.幸运的是,这一切都在您的控制台测试中; 如果您使用正确的输入编码阅读网站的响应,它应该都可以正常工作.

对于您的控制台测试,让我们演示如果您从正确的ISO-8859-1字符串开始,它一切正常:

string = 'Norrlandsvägen'.encode('iso-8859-1')
# => "Norrlandsv\xE4gen"
string = string.encode('utf-8')
# => "Norrlandsvägen"
Run Code Online (Sandbox Code Playgroud)

编辑对于您的具体问题,这应该工作:

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')
Run Code Online (Sandbox Code Playgroud)