지난 주 기사에서 대부분의 인코딩 문제를 해결하는 짧은 프로세스를 배웠습니다. 하지만 해결하기 훨씬 어려운 인코딩 문제가 하나 있습니다.
나는 당신이 그것을 보았다는 것을 알고 있습니다. (아니면 보신 적 있으신가요?) 둥근 따옴표가 ’로 바뀌거나 em-dash가 —로 바뀔 때입니다. 그것은 당신이 미쳤다고 생각하게 만들 것입니다. 제대로 작동해야 합니다!
거대한 테이블을 만들어 나쁜 캐릭터를 찾아 좋은 캐릭터로 교체할 수 있습니다.
[{broken: '–', fixed: "—"}
{broken: "—", fixed: "–"}
{broken: "‘", fixed: "‘"}
{broken: "’", fixed: "’"}
{broken: "“", fixed: "“"}
{broken: "â€", fixed: "”"}, ...]
하지만 깨진 문자를 수정하는 더 쉽고 안정적인 방법이 있습니다.
좋은 타이포그래피가 항상 깨지는 이유는 무엇입니까?
지난주에 인코딩은 의미 없는 바이트 그룹을 표시 가능한 문자로 바꾸는 방법일 뿐이라는 것을 배웠습니다. 256개 이상의 가능한 문자가 있기 때문에 모든 문자를 단일 바이트로 나타낼 수는 없습니다. 따라서 중괄호 ’
와 같은 일부 문자는 , 하나 이상의 바이트로 표현됨:
irb(main):001:0> "they’re".bytes
=> [116, 104, 101, 121, 226, 128, 153, 114, 101]
문자열이 7자뿐이지만 9바이트로 표시됩니다!
중괄호에만 집중하는 경우:
irb(main):002:0> "’".bytes
=> [226, 128, 153]
3바이트를 사용하는 것을 볼 수 있습니다. 그리고 우리의 엉망인 문자열은 딱 하나 있어야 하는 세 개의 문자를 가지고 있습니다. 우연이 아닌 것 같죠?
이 세 바이트는 UTF-8로 읽어야 하는 것 같으며 여기에서 중괄호를 나타냅니다. 대신 각 바이트 다른 캐릭터로 나타납니다. 따라서 어떤 인코딩이 [226, 128, 153]
를 나타낼 것입니까? ’
로 ? 인기 있는 인코딩의 몇 가지 표를 보면 Windows-1252임을 알 수 있습니다.
irb
에서 확인할 수 있습니다. :
irb(main):003:0> "they’re".force_encoding("Windows-1252").encode("UTF-8")
=> "they’re"
(마지막 .encode("UTF-8")
가 필요합니다. 콘솔에 문자열을 표시합니다.)
그래! 그것이 문제입니다. 하지만 상황은 더욱 악화됩니다.
데이터는 UTF-8이어야 하지만 Windows-1252로 잘못 읽힙니다. 그러나 아마도 그 데이터를 UTF-8로 데이터베이스나 파일에 저장할 것입니다. Ruby는 UTF-8로 변환하는 데 도움이 되므로 결과는 다음과 같습니다.
irb(main):004:0> "they’re".force_encoding("Windows-1252").encode("UTF-8")
=> "they’re"
irb(main):005:0> "they’re".force_encoding("Windows-1252").encode("UTF-8").bytes
=> [116, 104, 101, 121, 195, 162, 226, 130, 172, 226, 132, 162, 114, 101]
문자열이 두 번 잘못 인코딩되었습니다. . 그 깨진 캐릭터는 이제 있어야 할 것처럼 보입니다. 그리고 어떻게 된 일인지 모른다면 얽힌 것을 푸는 것이 거의 불가능할 것입니다.
해결 방법은 무엇입니까?
어떻게 하면 정상으로 되돌릴 수 있습니까? 문제를 거꾸로 생각해 봅시다.
-
UTF-8 문자열이 있습니다. (그들은)
-
Windows-1252 문자열에서 변환, (그들은)
-
어떤 바이트가 이어야 하는지 UTF-8로 읽음(그들은)
이 문제를 해결하려면 이전 단계를 따르기만 하면 됩니다. encode
사용 UTF-8 문자열을 Windows-1252 문자열로 다시 변환합니다. 그런 다음 force_encoding
을 사용합니다. 잘못 인코딩된 Windows-1252 문자열을 UTF-8로 읽도록 하려면:
irb(main):006:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they’re"
수정되었습니다!
한 가지 작은 문제가 있습니다...
불행히도 많은 파일이나 데이터베이스 레코드에 잘못 인코딩된 데이터가 있기 때문에 이 문제를 발견했을 것입니다. 그리고 모든 파일이나 레코드가 반드시 잘못 인코딩된 것은 아닙니다. 좋은 데이터와 나쁜 데이터가 혼합되어 있을 수 있습니다. 특히 해당 데이터가 귀하의 사이트를 방문하는 사람들로부터 온 경우
이 경우 모든 문자열에서 해당 코드를 맹목적으로 실행할 수는 없습니다.
irb(main):007:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they’re"
irb(main):008:0> "they’re".encode("Windows-1252").force_encoding("UTF-8")
=> "they\x92re"
좋은 데이터로 실행하면 나쁜 데이터로 바뀔 뿐입니다. 그래서 당신은 무엇을 할 수 있습니까?
휴리스틱을 사용할 수 있습니다. â
와 같이 잘못된 문자 중 하나가 포함된 문자열만 변경합니다. . â
와 같은 문자가 있으면 잘 작동합니다. 유효한 문자열에는 표시되지 않습니다.
하지만 마지막으로 이런 종류의 버그를 수정했을 때 안전하게 플레이하고 싶었습니다. 도움이 되는 또 다른 유용한 도구인 제 눈을 사용했습니다.
잘못 인코딩된 문자열을 발견할 때마다 대체 문자열과 함께 인쇄했습니다.
Changing title with ID 6 from "They’re over there!" to "They’re over there!"
이렇게 하면 변경된 소수의 문자열을 확인하고 더 이상 끊어지지 않는지 확인할 수 있습니다.
두통이 있는 것 같아요
지난 주에 말했듯이 동일한 데이터에 대한 다양한 해석을 머리 속에 그대로 유지하는 것은 어렵습니다! 하지만 혼란스럽다면 irb
콘솔이 도움이 될 것입니다. 그래서 그것을 시도! 하나를 열고 —
사이를 앞뒤로 이동할 수 있는지 확인하십시오. 및 —
, 또는 “
및 “
.
이렇게 복잡한 아이디어를 연습하는 것이 필요할 때 자신감을 느끼는 가장 빠른 방법입니다. 그리고 Rracticing Rails의 무료 샘플 장에서 , 이를 수행하기 위한 최고의 기술과 프로세스를 배우게 됩니다.