这就是它的样子。 您的输入文件包含一个™
字符,它采用UTF-8编码。 但是当你阅读它时,由于你没有指定编码,Ruby假定它是你系统的默认编码IBM437(你必须在Windows上)。
这与此基本相同:
>> input = "™"
=> "™"
>> input.encoding
=> #<Encoding:UTF-8>
>> input.force_encoding 'ibm437'
=> "\xE2\x84\xA2"
请注意, force_encoding
不会更改实际字符串,只会更改与其关联的标签。 这与您的情况相同,只有您通过不同的路线到达此处(通过阅读文件)。
该网页也有一个™
符号,也编码为UTF-8,但在这种情况下,Ruby的编码是正确的(Watir可能使用页面中的标题):
>> web_page = '™'
=> "™"
>> web_page.encoding
=> #<Encoding:UTF-8>
现在,当您尝试比较这两个字符串时,会出现兼容性错误,因为它们具有不同的编码:
>> web_page.include? input
Encoding::CompatibilityError: incompatible character encodings: UTF-8 and IBM437
from (irb):11:in `include?'
from (irb):11
from /Users/matt/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
如果两个字符串中的任何一个只包含ASCII字符(即代码点少于128),那么这种比较就可以了。 UTF-8和IBM437都是ASCII的超集,如果它们都包含ASCII范围之外的字符,则它们只是不兼容。 这就是您在输入文件具有™
时才开始看到此行为的原因。
修复是告知Ruby输入文件的实际编码是什么。 您可以使用已加载的字符串执行此操作:
>> input.force_encoding 'utf-8'
=> "™"
您也可以在读取文件时执行此操作 ,例如(有几种方法可以读取文件,它们都应该允许您明确指定编码):
input = File.read("input_file.txt", :encoding => "utf-8")
# now input will be in the correct encoding
注意,在这两个字符串中都没有被更改,它仍然包含相同的字节,但Ruby现在知道它的正确编码。
现在比较应该可行:
>> web_page.include? input
=> true
无需encode
字符串进行encode
。 如果你这样做会发生什么。 首先,如果您将编码更正为UTF-8,则编码为IBM437:
>> input.force_encoding("utf-8").encode("IBM437", replace: nil)
Encoding::UndefinedConversionError: U+2122 from UTF-8 to IBM437
from (irb):16:in `encode'
from (irb):16
from /Users/matt/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
IBM437不包含™
字符,因此您不能将包含它的字符串编码为此编码而不会丢失数据。 默认情况下,Ruby会在发生这种情况时引发异常。 您可以使用:undef
选项强制编码,但符号丢失:
>> input.force_encoding("utf-8").encode("IBM437", :undef => :replace)
=> "?"
如果你走另一条路,首先使用force_encoding
到IBM437,然后编码为UTF-8,你得到字符串Γäó
:
>> input.force_encoding("IBM437").encode("utf-8", replace: nil)
=> "Γäó"
就Ruby而言,该字符串已经采用IBM437编码,因此force_encoding
不会执行任何操作。 的UTF-8表示™
是三个字节0xe2 0x84 0xa2
,当解释为IBM437这些字节对应于这里看到的三个字符然后被转化为它们的UTF-8表示。
(这两个结果与您在问题中描述的内容相反,因此我的评论如上所述。我假设这只是一个复制粘贴错误。)