文字列を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"
_
Iso-8859-1のNorrlandsvägenがutf-8のNorrlandsvägenに変換される理由がわかりません。
エンコード、エンコード!、エンコード(destinationEncoding、originalEncoding)、iconv、force_encoding、および考えられるあらゆる種類の奇妙な回避策を試しましたが、何も機能しないようです。誰かが私を助けて/私を正しい方向に向けることができますか?
ルビー初心者はまだ狂ったように髪を引っ張っていますが、ここでのすべての返信に感謝しています...:)
この質問の背景:いくつかのWebサイト(iso-8859-1エンコーディング)からxmlファイルをダウンロードしてストレージに保存するgemを作成していますが、最初に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
_
しかし、最後の行は私に次のエラーを与えます:
_Encoding::UndefinedConversionError - "\xC3" from ASCII-8BIT to UTF-8
_
以下の@Amadanの回答のおかげで、実行すると_\xC3
_が実際にirbに表示されることに気付きました。
_irb(main):001:0> string = 'ä'
=> "ä"
irb(main):002:0> string.force_encoding('iso-8859-1')
=> "\xC3\xA4"
_
また、string.encode(originalEncoding)
の結果に新しい変数を割り当てようとしましたが、さらに奇妙なエラーが発生しました。
_newString = string.encode(originalEncoding)
puts "#{newString.encoding}" # can't even get to this line...
newString.encode!('utf-8')
_
エラーは_Encoding::UndefinedConversionError - "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to ISO-8859-1
_です
私はまだこのエンコーディングの混乱のすべてでかなり迷っていますが、私はすべての返信に本当に感謝しており、みんなが私にくれたのを助けます!トンありがとう! :)
UTF-8で文字列を割り当てます。 ä
が含まれています。 UTF-8は、ä
を2バイトで表します。
string = 'ä'
string.encoding
# => #<Encoding:UTF-8>
string.length
# 1
string.bytes
# [195, 164]
次に、基になる表現を実際に変更せずに、バイトをISO-8859-1であるかのように強制的に解釈します。これにはä
は含まれていません。 Ã
と¤
の2文字が含まれています。
string.force_encoding('iso-8859-1')
# => "\xC3\xA4"
string.length
# 2
string.bytes
# [195, 164]
次に、それをUTF-8
に変換します。これは再解釈ではなく翻訳であるため、2文字を保持しますが、UTF-8でエンコードされます。
string = string.encode('utf-8')
# => "ä"
string.length
# 2
string.bytes
# [195, 131, 194, 164]
あなたが見逃しているのは、あなたが元々あなたのWebサービスからのようにISO-8859-1文字列を持っていないという事実です-あなたは意味不明です。幸い、これはすべてコンソールテストに含まれています。適切な入力エンコーディングを使用してWebサイトの応答を読み取れば、すべて正常に機能するはずです。
コンソールテストでは、適切なISO-8859-1文字列から始めれば、すべてが機能することを示しましょう。
string = 'Norrlandsvägen'.encode('iso-8859-1')
# => "Norrlandsv\xE4gen"
string = string.encode('utf-8')
# => "Norrlandsvägen"
[〜#〜] edit [〜#〜]特定の問題の場合、これは機能するはずです。
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')
force_encoding と encode には違いがあります。前者は文字列のエンコーディングを設定しますが、後者は実際には文字列の内容を新しいエンコーディングにトランスコードします。したがって、次のコードが問題の原因になります。
string = "Norrlandsvägen"
string.force_encoding('iso-8859-1')
puts string.encode('utf-8') # Norrlandsvägen
次のコードは実際にはコンテンツを正しくエンコードします。
string = "Norrlandsvägen".encode('iso-8859-1')
string.encode!('utf-8')
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>
上記の答えは的確でした。具体的にはここでこの点:
Force_encodingとencodeには違いがあります。前者は文字列のエンコーディングを設定しますが、後者は実際には文字列の内容を新しいエンコーディングにトランスコードします。
私の状況では、iso-8859-1エンコーディングのテキストファイルがありました。デフォルトでは、RubyはUTF-8エンコーディングを使用するため、エンコーディングを指定せずにファイルを読み取ろうとすると、エラーが発生します。
_results = File.read(file)
results.encoding
=> #<Encoding:UTF-8>
results.split("\r\n")
ArgumentError: invalid byte sequence in UTF-8
_
異なるエンコーディングの文字が異なるバイト長で表されるため、無効なバイトシーケンスエラーが発生します。したがって、FileAPIにエンコーディングを指定する必要があります。 force_encodingのように考えてください。
_results = File.read(file, encoding: "iso-8859-1")
_
だからすべてが良いですよね?いいえ、UTF-8文字エンコードを使用してiso-8859-1文字列の解析を開始する場合は除きます。
_results = File.read(file, encoding: "iso-8859-1")
results.each do |line|
puts line.split('¬')
end
Encoding::CompatibilityError: incompatible character encodings: ISO-8859-1 and UTF-8
_
なぜこのエラー? '¬'はUTF-8として表されるためです。 ISO-8859-1文字列に対してUTF-8文字シーケンスを使用しています。それらは互換性のないエンコーディングです。したがって、ファイルをISO-8859-1として読み取った後、RubyにそのISO-8859-1をUTF-8にエンコードするように要求できます。これで、次の操作を行うことができます。 UTF-8文字列であるため、問題はありません。
_results = File.read(file, encoding: "iso-8859-1").encode('UTF-8')
results.encoding
results = results.split("\r\n")
results.each do |line|
puts line.split('¬')
end
_
最終的に、一部のRuby APIでは、force_encoding('ISO-8859-1')
を使用する必要はありません。代わりに、APIに期待されるエンコーディングを指定するだけです。ただし、に変換し直す必要があります。 UTF-8文字列で解析する場合はUTF-8。