2012-03-21 4 views
7

내 레일 3.2.2/루비 1.9.3 응용 프로그램과 같은 검색 요청 가져옵니다루비에서 문자 인코딩을 결정 1.9.3

http://booko.com.au/books/search?q=Fran%E7ois+Vergniolle+de+Chantal 

루비/레일이 쿼리를 받아 그것을 디코딩 -하지만 UTF-의 가정을 8.

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 

이 처리하는 올바른 방법은 무엇입니까 :

invalid byte sequence in UTF-8 
app/models/product.rb:694:in `upcase' 

은 내가 이런 일을 생각 : 어떤 시점에서 나는거야? 올바른 인코딩으로 코드 변환하고 싶습니다 -하지만 어떻게 현재 인코딩을 결정합니까?

q = q.unpack('C*').pack('U*') 

이 처리하는 올바른 방법은 무엇입니까 : 나는 어딘가의 블로그에서 발견

q.encode!("ISO-8859-1", "UTF-8", :invalid => :replace, :undef => :replace, :replace => "") 

또는 일을 뭔가 : 나는 현재하고 있어요 무엇, 바로 가정입니다 그것은 LATIN1입니까?

편집 는 서버가 제대로 "콘텐츠 형식 : text/html; 문자셋 = UTF-8"을 보내는 헤더를 클라이언트에. 이 페이지에는 적절한 메타 태그도 포함되어 있습니다. 'meta http-equiv = "content-type"content = "text/html; charset = UTF-8"'

클라이언트에게 인코딩을 알리는 다른 방법이 있는지 확실하지 않습니다 사용?

+0

'# coding : UTF-8'을'app/models/product.rb'의 맨 위에 쓰면 어떨까요? 그 오류를 해결해야한다고 생각합니다. 이 솔루션에 만족하십니까? – ck3g

+0

@ ck3g, 아니요, 여기 엔 파일 인코딩이 아닙니다. – fl00r

+0

같은 바이트 '0xE7'이 Latin1 이외의 다른 인코딩에서 유효 문자 일 수 있기 때문에 올바른 인코딩을 결정하기 위해 사전을 사용해야합니다. –

답변

5

문자 ç는 URL에서 % E7로 인코딩됩니다. 이것이 ISO-8859-1이 ç을 인코딩하는 방법입니다. ISO-8859-1 문자 집합은 단일 바이트 문자를 나타냅니다. ç를 나타내는 바이트는 E7로 16 진수로 나타낼 수 있습니다.

유니 코드의 경우 ç의 코드 포인트는 U + 00E7입니다. 코드 포인트 (E7)가 인코딩 (16 진수의 E7)과 동일한 ISO-8859-1과 달리, 유니 코드는 UTF-8, UTF-16 및 UTF-32와 같은 여러 인코딩 스키마를 가지고 있습니다. UTF-8은 U + 00E7 (ç)을 2 바이트로 인코딩합니다 - C3 A7.

ç 다른 인코딩 방법은 here을 참조하십시오.

ISO-8859-1의 U + 00E7과 E7 둘 다 "E7"을 사용하는 이유에 대해 유니 코드의 처음 256 코드 포인트는 ISO-8859-1과 동일하게 만들어졌습니다.

이 URL이 UTF-8 인 경우 ç은 % C3 % A7로 인코딩됩니다. RFC2616에 대한 (매우 제한적인) 이해는 URL의 기본 인코딩이 (현재) ISO-8859-1이라는 것입니다. 따라서 이것은 ISO-8859-1로 인코딩 된 URL 일 가능성이 큽니다.(플러스 여기

unless query.valid_encoding? 
    query.encode!("UTF-8", "ISO-8859-1", :invalid => :replace, :undef => :replace, :replace => "") 
end 

는 IRB의 과정이다 : 어느 것이 가장 좋은 방법이 아닌 경우 인코딩이 유효하고 있는지 확인은 ISO-8859-1 가정 및 UTF-8로 트랜스 코딩하는 아마 의미 끝까지 재미있게 도주)

a = CGI.unescape("%E7") 
=> "\xE7" 
a.encoding 
=> #<Encoding:UTF-8> 
a.valid_encoding? 
=> false 
b = a.encode("UTF-8", "ISO-8859-1") # From ISO-8859-1 -> UTF-8 
=> "ç" 
b.encoding 
=> #<Encoding:UTF-8> 
CGI.escape(b) 
=> "%C3%A7" 
0

URL 인코딩 문자열 인 것 같습니다. 여기에 참고로 는 인코딩 된 문자의 목록입니다 http://www.degraeve.com/reference/urlencoding.php

불행하게도 CGI 라이브러리는 UTF-8 문제를 가지고 있으며, 언 이스케이프 방법이 공간 같은 일부 문자가 잘 작동하는 경우, 그것은 다른 사람들과 잘 작동하지 않습니다.

require'cgi' 
a = "Fran%E7ois+Vergniolle+de+Chantal" 
a= a.gsub('+', ' ').gsub('%E7','ç') 
puts a 
=> François Vergniolle de Chantal 

a = "Fran%E7ois+Vergniolle+de+Chantal" 
a = CGI::unescape(a) 
puts a 
=> Franis Vergniolle de Chantal 

gsub와 인코딩 된 문자 목록을 사용하여 고유 한 방법을 구현할 수 있습니까?

+0

참조 할 문제는 무엇입니까? http://ideone.com/hWnj6 –

+0

@ MladenJablanović 문자열이 UTF-8 인 경우 latin1에 force_encode를하지 않아도 UTF-8로 인코딩 할 수 있습니까? % E7은 두 문자 집합에 세 딜라가있는 작은 C이므로? % C3 % A7이 % E7 대신 UTF-8에서이 문자의 올바른 인코딩 일 수 있습니다. – dkam

+0

@Mladen Jablanović –

관련 문제