My Rails 3.2.2 / Ruby 1.9.3应用程序获取搜索请求,例如:
http://booko.com.au/books/search?q=Fran%E7ois+Vergniolle+de+Chantal
Ruby / Rails接受此查询并对其进行解码 - 但假设它是UTF-8 . 在某些时候,我得到一个:
invalid byte sequence in UTF-8
app/models/product.rb:694:in `upcase'
我认为它正在做这样的事情:
q="Fran%E7ois+Vergniolle+de+Chantal"
=> "Fran%E7ois+Vergniolle+de+Chantal"
CGI.unescape( q )
=> "Fran\xE7ois Vergniolle de Chantal"
CGI.unescape( q ).encoding.name
=> "UTF-8"
CGI.unescape( q ).valid_encoding?
=> false
处理这个问题的正确方法是什么?我想将其转码为正确的编码 - 但我如何确定当前的编码?我现在正在做的,只是假设它是LATIN1:
q.encode!("ISO-8859-1", "UTF-8", :invalid => :replace, :undef => :replace, :replace => "")
或者做某些我在博客上找到的东西:
q = q.unpack('C*').pack('U*')
处理这个问题的正确方法是什么?
Edit 服务器正在向客户端正确发送"Content-Type: text/html; charset=utf-8"标头 . 该页面还包含相应的元标记:'meta http-equiv= 2595953 content= 2595954 '
不确定是否有另一种方法告诉客户端使用哪种编码?
2 回答
字符ç在URL中编码为%E7 . 这就是ISO-8859-1编码的方式 . ISO-8859-1字符集表示具有单个字节的字符 . 表示ç的字节可以用十六进制表示为E7 .
在Unicode中,ç的代码点为U 00E7 . 与ISO-8859-1不同,其中代码点(E7)与其编码(十六进制中的E7)相同,Unicode具有多种编码方案,例如UTF-8,UTF-16和UTF-32 . UTF-8将U 00E7(ç)编码为两个字节 - C3 A7 .
有关编码ç的其他方法,请参见here .
至于为什么ISO-8859-1中的U 00E7和E7都使用"E7",Unicode中的前256个代码点与ISO-8859-1相同 .
如果此URL为UTF-8,则ç将编码为%C3%A7 . 我(非常有限)对RFC2616的理解是,URL的默认编码是(当前)ISO-8859-1 . 因此,这很可能是ISO-8859-1编码的URL . 这意味着,最好的方法可能是检查编码是否有效,如果没有,则假设它是ISO-8859-1并将其转码为UTF-8:
这是IRB中的过程(加上最后的转义以获得乐趣)
它似乎是一个url编码的字符串 . 这里有一个编码字符列表供参考:http://www.degraeve.com/reference/urlencoding.php
不幸的是,CGI库存在utf-8的问题,如果unescape方法适用于某些字符如空格,则它与其他字符不兼容 .
也许你可以使用gsub和编码字符列表实现自己的方法?