Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

彼らから彼らへの行き方

先週の記事では、ほとんどのエンコーディングの問題を解決する短いプロセスを学びました。 しかし、解決がはるかに難しいエンコーディングの問題が1つあります。

あなたがそれを見たことがあると思います。 (または、見たことがあるかもしれませんか?)中の引用符が「」に変わるとき、または全角ダッシュが「」に変わるときです。夢中になっていると思わせるでしょう。うまくいくはずです!

巨大なテーブルを作成して、悪いキャラクターを見つけて、良いキャラクターに置き換えることができます:

[{broken: '–',    fixed: "—"}
 {broken: "—",    fixed: "–"}
 {broken: "‘",    fixed: "‘"}
 {broken: "’",    fixed: "’"}
 {broken: "“",    fixed: "“"}
 {broken: "”", fixed: "”"}, ...]

しかし、これらの壊れた文字を修正するためのより簡単で信頼性の高い方法があります。

なぜ良いタイポグラフィは常に壊れているのですか?

先週、エンコーディングは意味のないバイトのグループを表示可能な文字に変換する方法にすぎないことを学びました。 256を超える可能性のある文字があるため、すべての文字を1バイトで表すことができるわけではありません。したがって、中引用符などの一部の文字 、は複数のバイトで表されます:

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バイトを使用していることがわかります。そして、私たちのめちゃくちゃな文字列、they’reには、3つの文字があります。それは偶然の一致ではないようですよね?

これらの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]

文字列が正しくエンコードされていません2回 。これらの壊れたキャラクターは、そこにいるはずのように見えます。そして、それがどのように起こったのかを知らなければ、それを解きほぐすことはほとんど不可能でしょう。

どのように修正しますか?

どうやって物事を正常に戻すのですか?問題を逆に考えてみましょう:

  • 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"

修正済み!

1つの小さな問題があります…

残念ながら、この問題は、大量のファイルまたはデータベースレコードにデータが正しくエンコードされていないために発生した可能性があります。また、すべてのファイルまたはレコードが必ずしも正しくエンコードされているわけではありません。良いデータと悪いデータが混在している可能性があります。 特に そのデータがあなたのサイトを訪れた人々からのものである場合。

その場合、すべての文字列でそのコードを盲目的に実行することはできません:

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"

良いデータで実行すると、悪いデータに変わるだけです。では、何ができるでしょうか?

ヒューリスティックを使用できます。âのように、不正な文字の1つが含まれている文字列のみを変更してください。 。 これは、âのような文字の場合にうまく機能します 有効な文字列には表示されません。

前回この種のバグを修正したときは、安全にプレイしたかったのですが。私は別の便利なツールを使って助けました:私の目。

正しくエンコードされていない文字列を見つけたときはいつでも、その文字列とその代わりの文字列を印刷しました:

Changing title with ID 6 from "They’re over there!" to "They’re over there!"

そうすれば、変更された少数の文字列をスポットチェックして、それ以上壊れていないことを確認できます。

頭痛があると思います

先週言ったように、同じデータの異なる解釈を頭の中でまっすぐに保つのは難しいです!ただし、混乱している場合は、irbを調べてください。 コンソールが役立ちます。ぜひお試しください。 1つ開いて、間を行ったり来たりできるかどうかを確認します および— 、または および“

このような複雑なアイデアを実践することは、必要なときに自信を持って感じるための最速の方法です。 そして、 Practicing Railsの無料サンプルの章で 、それを行うための最良の技術とプロセスを学びます。


  1. AndroidアプリでURLからビットマップを取得するにはどうすればよいですか?

    この例は、AndroidアプリでURLからビットマップを取得する方法を示しています。 ステップ1 − Android Studioで新しいプロジェクトを作成し、[ファイル]⇒[新しいプロジェクト]に移動して、新しいプロジェクトを作成するために必要なすべての詳細を入力します。 ステップ2 −次のコードをres / layout/activity_main.xmlに追加します。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://

  2. ChromeでGmailから通知を受け取る方法

    Gmailで新しいメッセージがないかパソコンを常にチェックする必要はありません。代わりに、ChromeのGmailから通知を受け取ります。基本的な通知については、Gmail内の設定を使用してください。または、より高度なオプションについては、Gmailのウィンドウやタブが閉じている場合でも、無料のブラウザ拡張機能で最新情報を入手できます。 Gmailでの通知 拡張機能をインストールしたくない場合は、Gmailアカウント内の通知設定を使用してください。有効にすると、Chrome、Safari、Firefox、およびその他のChromiumベースのブラウザでGmailから通知を受け取ることができま