Ruby不兼容字符编码

Ruby不兼容字符编码,ruby,encoding,watir,watir-webdriver,Ruby,Encoding,Watir,Watir Webdriver,我目前正在尝试编写一个脚本,该脚本迭代输入文件并检查网站上的数据。如果它找到了新的数据,它会打印到它经过的终端,如果没有,它会告诉我它失败了。对于已删除的数据,反之亦然。它工作正常,直到我收到的输入文件包含“™" 当ruby到达那一行时,它抛出了一个错误: PDAPWeb.rb:73:“包含”中:不兼容的字符编码:UTF-8和IBM437 (编码::CompatibilityError) 有问题的行是一个简单的检查,以查看页面上是否存在文本 if browser.text.include? (p

我目前正在尝试编写一个脚本,该脚本迭代输入文件并检查网站上的数据。如果它找到了新的数据,它会打印到它经过的终端,如果没有,它会告诉我它失败了。对于已删除的数据,反之亦然。它工作正常,直到我收到的输入文件包含“™" 当ruby到达那一行时,它抛出了一个错误:

PDAPWeb.rb:73:“包含”中:不兼容的字符编码:UTF-8和IBM437 (编码::CompatibilityError)

有问题的行是一个简单的检查,以查看页面上是否存在文本

if browser.text.include? (program_name)
其中program_name变量是从输入文件中解析的一段信息。在本例中,program_name包含前面提到的“TM”字符

经过一些研究,我发现在我的脚本开头添加一行#编码:utf-8可能会有所帮助,但到目前为止还没有被证明是有用的

我把它添加到我的program_name变量中,以查看它是否有帮助(它允许我的脚本在没有错误的情况下运行),但是现在它没有正确地找到应该找到的TM字符

program_name = record[2].gsub("\n", '').force_encoding("utf-8").encode("IBM437", replace: nil)
这似乎将TM字符转换为:Γäó


我想也许我把IBM437和utf-8的部件颠倒了,所以我试了相反的方法

program_name = record[2].gsub("\n", '').force_encoding("IBM437").encode("utf-8", replace: nil)
我现在在尝试运行脚本时收到此错误

PDAPWeb.rb:48:in'encode':U+2122从UTF-8到IBM437(编码::UndefinedConve rsionError)

我正在使用ruby 1.9.3p392(2013-02-22),我不确定是否应该升级,因为这是我公司安装的标准版本


我的编码是否不正确并导致转换TM字符时出错?

下面是它的情况。您的输入文件包含
字符,它是UTF-8编码。但是,当您阅读它时,由于您没有指定编码,Ruby假定它是系统默认的IBM437编码(您必须在Windows上)

这与此基本相同:

>输入=”™"
=> "™"
>>输入编码
=> #
>>input.force_编码“ibm437”
=>“\xE2\x84\xA2”
请注意,
force_encoding
不会更改实际字符串,只会更改与其关联的标签。这与您的情况相同,只是您通过不同的路径(通过读取文件)到达此处

该网页还有一个
symbol,也被编码为UTF-8,但在本例中,Ruby的编码是正确的(Watir可能使用页面的标题):

>网页™'
=> "™"
>>网页编码
=> #
现在,当您尝试比较这两个字符串时,会出现兼容性错误,因为它们的编码不同:

>web\u page.include?输入
编码::兼容性错误:不兼容的字符编码:UTF-8和IBM437
from(irb):11:include
来自(irb):11
from/Users/matt/.rvm/rubies/ruby-2.2.1/bin/irb:11:in`'
如果两个字符串中的任何一个仅包含ASCII字符(即代码点小于128)那么这个比较就行了。UTF-8和IBM437都是ASCII的超集,只有当它们都包含ASCII范围以外的字符时才不兼容。这就是为什么只有当输入文件有

修复方法是通知Ruby输入文件的实际编码是什么。您可以使用已加载的字符串执行此操作:

>> input.force_encoding 'utf-8'
=> "™"
您也可以在以下情况下执行此操作,例如(有几种读取文件的方法,它们都应允许您显式指定编码):

注意,这两个字符串都没有改变,它仍然包含相同的字节,但是Ruby现在知道了它的正确编码

现在比较应该可以了:

>web\u page.include?输入
=>正确

不需要输入字符串。如果您这样做,会发生以下情况。首先,如果您将编码更正为UTF-8,然后将编码更改为IBM437:

>输入。强制编码(“utf-8”)。编码(“IBM437”,替换为:无)
编码::未定义的转换器错误:U+2122从UTF-8到IBM437
from(irb):16:in'encode'
起始(irb):16
from/Users/matt/.rvm/rubies/ruby-2.2.1/bin/irb:11:in`'
不包括
字符,因此您无法将包含该字符的字符串编码为此编码而不丢失数据。默认情况下,Ruby会在这种情况下引发异常。您可以使用
:undef
选项强制编码,但符号丢失:

>input.force_编码(“utf-8”).encode(“IBM437”,:unde=>:replace)
=> "?"
如果您选择另一种方式,首先使用
强制_编码
到IBM437,然后编码到UTF-8,您将得到字符串
Γäó

>输入。强制编码(“IBM437”)。编码(“utf-8”,替换:nil)
=> "Γäó"
就Ruby而言,字符串已经采用IBM437编码,因此
force_编码
没有任何作用™
是三个字节
0xe2 0x84 0xa2
,当解释为IBM437时,这些字节对应于此处看到的三个字符,然后将其转换为UTF-8表示形式


(这两个结果与您在问题中所描述的相反,因此我在上面进行了评论。我假设这只是一个复制粘贴错误。)

您将编码到
IBM437
有什么原因吗?我不确定我的编码顺序是否正确,我只是按照它在问题中所说的去做错误最初是什么(在我添加任何编码之前)“我想我可能把IBM437和utf-8部分颠倒了,所以我尝试了相反的方法,现在在尝试运行脚本时收到了这个错误”你能显示这个代码吗。有些东西没有意义。使用
/\u{2122}/
表示TM符号可能会对您有所帮助。例如,请尝试
browser.goto'http://graphemica.com/%E2%84%A2“
注意,
brow
input = File.read("input_file.txt", :encoding => "utf-8")
# now input will be in the correct encoding